コマンドの複数行出力を含む変数があります。変数から行ごとに出力を読み取る最も効率的な方法は何ですか?
例えば:
jobs="$(jobs)"
if [ "$jobs" ]; then
# read lines from $jobs
fi
Whileループをプロセス置換で使用できます。
while read -r line
do
echo "$line"
done < <(jobs)
複数行の変数を読み取る最適な方法は、空白のIFS
変数とprintf
変数を後続の改行で設定することです。
# Printf '%s\n' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
while IFS= read -r line
do
echo "$line"
done < <(printf '%s\n' "$var")
注: shellcheck sc2031 のように、サブシェルの作成を(微妙に)回避するために、パイプよりもプロセス置換の使用が推奨されます。
また、変数にjobs
という名前を付けると、一般的なシェルコマンドの名前にもなるため、混乱を招く可能性があることに注意してください。
問題:whileループを使用すると、サブシェルで実行され、すべての変数が失われます。解決策:forループを使用する
# change delimiter (IFS) to new line.
IFS_BAK=$IFS
IFS=$'\n'
for line in $variableWithSeveralLines; do
echo "$line"
# return IFS back if you need to split new line by spaces:
IFS=$IFS_BAK
IFS_BAK=
lineConvertedToArraySplittedBySpaces=( $line )
echo "{lineConvertedToArraySplittedBySpaces[0]}"
# return IFS back to newline for "for" loop
IFS_BAK=$IFS
IFS=$'\n'
done
# return delimiter to previous value
IFS=$IFS_BAK
IFS_BAK=
最近のbashバージョンでは、mapfile
またはreadarray
を使用して、コマンド出力を配列に効率的に読み取ります
$ readarray test < <(ls -ltrR)
$ echo ${#test[@]}
6305
免責事項:恐ろしい例ですが、自分でlsよりも使用するコマンドを多用することができます
<<<を使用して、改行で区切られたデータを含む変数から単純に読み取ることができます。
while read -r line
do
echo "A line of input: $line"
done <<<"$lines"