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