Bashスクリプトがあり、stdinの行を繰り返したり、渡された各引数を繰り返したい。
2つのループを持つ必要がないようにこれを書くためのきちんとした方法はありますか?
#!/bin/bash
# if we have command line args...
if [ -t 0 ]
then
# loop over arguments
for arg in "$@"
do
# process each argument
done
else
# loop over lines from stdin
while IFS= read -r line; do
# process each line
done
fi
編集:私はこれを頻繁に実行したいのですが、常に2つのループを作成してから関数を呼び出すので、単一ループを使用する一般的なソリューションを探しています。それでは、stdinを配列に変換して代わりに単一のループを使用できますか?
答え1
ループに関するデータを生成しますwhile read
。
#!/bin/sh
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%s\n' "$@"
else
# No command line arguments.
# Just pass stdin on.
cat
fi |
while IFS= read -r string; do
printf 'Got "%s"\n' "$string"
done
concat
ループをまたは同様のものに置き換えて例を実行できます。while read
tr '\n' ','
また、-t
テストはコマンドライン引数があるかどうかを示していません。
または、処理両方コマンドライン引数と標準入力(シーケンス):
#!/bin/sh
{
if [ "$#" -gt 0 ]; then
# We have command line arguments.
# Output them with newlines in-between.
printf '%s\n' "$@"
fi
if [ ! -t 0 ]; then
# Pass stdin on.
cat
fi
} |
while IFS= read -r string; do
printf 'Got "%s"\n' "$string"
done
または、一部の人が好きな短縮表記を使用してください。
#!/bin/sh
{
[ "$#" -gt 0 ] && printf '%s\n' "$@"
[ ! -t 0 ] && cat
} |
while IFS= read -r string; do
printf 'Got "%s"\n' "$string"
done
答え2
標準入力リダイレクトを使用することもできます。
#!/usr/bin/env bash
test -t 0 && exec < <(printf '%s\n' "$@")
while IFS= read -r line; do
echo "$line"
done
テスト:
test.sh Hello World
test.sh < /etc/passwd
答え3
具体的には、bash
次のようにできます。
if [ -t 0 ]; then
args=("$@")
else
readarray -t args
fi
for i in "${args[@]}"; do
...
done
答え4
STDIN記述子にアクセスして、次のこともできます。
for i in $(cat /dev/stdin) ; do echo $i ; done