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