引用符付きと引用符なしの文字列展開


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

1が2と異なる理由を理解していますが、3が2とは異なる出力を提供するのはなぜですか?出力についても説明してください。引用符は改行でどのように機能しますか?



回答:


19

引用符で囲まれていない変数(など$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 -fset +f)。

通常、上記の例で、の出力で単語の空白で区切られたリストをループする場合はxrandr、次のようにする必要があります。

  • $IFS空白で分割するには、デフォルト値のままにする(または設定を解除する)
  • or または文字(ファイル名生成パターンで使用されるワイルドカード)を出力しset -fないことが確実でxrandrない限り、ファイル名生成を無効にするために使用します。*?[

そしてinforループの一部でsplit + glob演算子のみを使用します(コマンド置換または変数展開のみを引用符で囲まないでください)。

set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done

あなたは(空でない)をループにしたい場合はラインxrandr出力は、セットに必要があると思い$IFS改行文字に:

IFS='
'

4

引用された改行は改行です。そのecho "$1"ため、echoに単一のコマンドライン引数を指定すると、改行が直接出力されます。

引用符で囲まれていない改行は空白です。そのecho $1ため、エコーするコマンドライン引数を多く与え、スペースで区切って次々に出力します。


引用符で囲まれていない改行は空白文字であり、ここでのIMOの動作の説明として本当に役立つには、あまりにも多くのショートカットです。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.