bash(または他のシェル)スクリプトでスペースの数が問題になるケースは何ですか


14

bash他のシェルスクリプトではスペースが重要であると言われましたが、何をしているのかわからない限り、スペースの存在を変更しないでください。「存在を変える」と私はどちらかなどが変化する、二つの非空白文字の間にスペースを挿入するか、二つの非空白文字の間にスペースを取り除く意味var="$val"するvar ="$val"、またはその逆。聞きたい

シェルスクリプトで単一のスペースを使用したり、複数の連続したスペースを使用したりすると、違いが生じる場合はありますか?

(もちろん、引用符でスペースを挿入/削除すると違いが生じます。例えば、からecho "a b"echo "a b"またはその逆に変更します。この些細な例以外の例を探しています。)

私はこの質問に出くわしましたが、その1つは2つの非スペース文字の間にスペースを追加および削除することです。

任意の助けをいただければ幸いです。可能であれば、より多くの種類のシェルを含めます。

回答:


19

シェルは、引用符の外で、空白(スペース、タブ、改行、キャリッジリターンなど)を単語/トークンの区切り文字として使用します。つまり:

  • 空白で区切られていないものは、1つの「単語」と見なされます。
  • 1つ以上の空白文字で区切られたものは、2つ(またはそれ以上)の単語と見なされます。

少なくとも1つある限り、各「モノ」間の空白文字の実際の数は重要ではありません。


ありがとうございました。私は反例を自分で見つけることができません。確認したいだけです。
ウェイジュン周

2
Bashは、フォームフィードと垂直タブも空白と見なします。
fpmurphy

本当。私はもともと「... newlinesなど」を書いてから、キャリッジリターンを明示的に追加するように変更しました。誤って「など」を落としました。
cas

スペースの数が非常に多く、プログラムがメモリに収まらない場合はどうなりますか?
Worse_Username

7
@Worse_Username空白はメモリに収まる必要はありません。8GBのRAMと20GBのスワップを備えたマシンで48GBスクリプトを作成しました。それはうまく動いた。空白をすべて処理するのに3分かかりましたが、最終的にechoコマンドと引数の間に空白が多く含まれたコマンドを正常に実行しました。
カスペルド

23

これはおそらく不正行為ですが、これは次のとおりです。

rm foo\ bar         # "delete the file named 'foo bar'"

これとは異なります:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

スペースは引用符で囲まれていませんが。;-)

より混乱させて、これ:

rm \
    foo          # "delete the file named 'foo'"

これとは異なります:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

同じように見えても!


スペースは引用符で囲まれていませんが、バックスラッシュは機能的に引用の形式に似ており、これを質問の「些細な例」と同じカテゴリに入れます。(しかし、興味深いです。)
デイビッドZ

12

我々は、スペース文字(について話していない場合U+0020)が、任意の空白文字(U+0020\n\t、など)、その後、ある特定の場合には、私の心に来る:ヒアドキュメント。

このコード(スペースを使用):

cat <<- 'EOF'
<space><space>foo
EOF

印刷されます:

  foo

しかし、このコード(タブを使用):

cat <<- 'EOF'
<tab><tab>foo
EOF

印刷されます:

foo

その理由は(POSIXが述べているように):

リダイレクト演算子がの場合<<-、すべての先行<tab>文字は入力行と後続の区切り文字を含む行から削除されます。


1
それは興味深い。私はヒアドキュメントについて考えましたが、<<-演算子を知りませんでした。どうもありがとうございました。
ウェイジュン周

ここでのドキュメントは引用されたテキストの形式であり、シェルコードではありません。シェルの単語分割は適用されません。
cas

2

また、割り当てステートメントを記述するときに効果があります。value FOO=xyzという名前の環境変数を作成すると言うように、equalsをスペースで区切ると、arg という名前のプログラムを呼び出していると考えられます。そのため、特定の構文に関しては重要です。FOOxyzFOO=xyz


通常FOO=xyz、内部シェル変数を作成しますが、環境変数は作成しません。あなたはset -aそれexport FOO=xyzを必要としています(つまり、非サブシェルサブプロセスの環境の一部にすること)
Hauke Laging
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.