for i in $(xrandr); do echo "$i" ; done
for i in "$(xrandr)"; do echo "$i"; done
for i in "$(xrandr)"; do echo $i; done
1が2と異なる理由を理解していますが、3が2とは異なる出力を提供するのはなぜですか?出力についても説明してください。引用符は改行でどのように機能しますか?
引用符で囲まれていない変数(_$var
_など)またはコマンド置換($(cmd)
または_`cmd`
_など)は、split + glob演算子ですボーンのようなシェルで。
つまり、それらの内容は、_$IFS
_特殊変数の現在の値(デフォルトでは、スペース、タブ、改行文字を含む)に従って分割されます。
そして、その分割の結果として生じる各Wordは、ファイル名の生成(globbingまたはとも呼ばれます)の対象になります。ファイル名の展開)、つまり、パターンと見なされ、そのパターンに一致するファイルのリストに展開されます。
したがって、for i in $(xrandr)
では、$(xrandr)
は引用符で囲まれていないため、スペース、タブ、および改行文字のシーケンスで分割されます。そして、その分割の結果として得られた各Wordは、一致するファイル名がチェックされ(または、どのファイルとも一致しない場合はそのまま残されます)、for
はそれらすべてをループします。
for i in "$(xrandr)"
では、コマンド置換が引用されているため、split + glob演算子を使用していないため、のループに1つのパスがあります。 one value:xrandr
の出力(コマンド置換が削除される末尾の改行文字なし)。
ただし、_echo $i
_では、_$i
_が再び引用解除されるため、_$i
_の内容が分割され、ファイル名生成の対象となり、それらが渡されますecho
コマンドの個別の引数として(およびecho
は、スペースで区切られた引数を出力します)。
学んだ教訓:
$IFS
_を設定するか、またはを有効にします。必要に応じてファイル名の生成を無効にします(_set -f
_、_set +f
_)。通常、上記の例では、xrandr
の出力で空白で区切られた単語のリストをループする場合は、次のことを行う必要があります。
$IFS
_をデフォルト値のままにする(または設定を解除する)と、空白で分割されますxrandr
が_set -f
_または_*
_または_?
_文字(ファイル名で使用されるワイルドカード)を出力しないことが確実でない限り、_[
_を使用してファイル名生成を無効にします生成パターン)そして、in
ループのfor
部分でのみsplit + glob演算子を使用します(コマンド置換または変数展開は引用符で囲まないままにします)。
_set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
_
xrandr
出力の(空でない)行をループする場合は、_$IFS
_を改行文字に設定する必要があります:
_IFS='
'
_
引用された改行は改行です。そう echo "$1"
はechoに単一のコマンドライン引数を与え、それは改行を直接出力します。
引用符で囲まれていない改行は空白です。そう echo $1
はechoに多くのコマンドライン引数を与え、スペースで区切ってそれらを次々に出力します。