3

私はbashの内部変数について読んでいて、この例に出くわしましたIFS:

output_args_one_per_line()
{
  for arg
  do
    echo "[$arg]"
  done #  ^    ^   Embed within brackets, for your viewing pleasure.
}

CASE1

IFS=" "
var=" a  b c   "

output_args_one_per_line $var
#OUTPUT
# [a]
# [b]
# [c]

CASE2

IFS=:
var=":a::b:c:::"               # Same pattern as above
CASE2   
                        # but substituting ":" for " "  ...
output_args_one_per_line $var
# []
# [a]
# []
# [b]
# [c]
# []
# []

さて、私の理解によれば、値IFSがデフォルト\t\nよりも先頭と末尾の空白が削除されている場合。したがって、case1 の場合、bash はvar出力をa b c参照します。

私によると、ケース2の場合、bashはここvarのように|a||b|c|||扱わ|spaceます。を使って確認しました

Noob@Noob:~/tmp$ IFS=$':' FOO=$":a::b:c:::"; echo $FOO $'x'
 a  b c   x

したがって、ケース 2 の期待される出力は次のとおりです。

# []
# [a]
# []
# []
# [b]
# [c]
# []
# []
# []

それで、誰かがvarケース2でbashがどのように扱っているか、そして私の理解のどこで間違っているのかを内部的に説明してもらえますか。

4

4 に答える 4

3

あなたの主張(「|」の代わりに「:」を使用するように編集):

私によると、case2 の場合、bash は var を :a::b:c::: と見なします。ここでは : をスペースとして扱います。

は偽です。空白ではなく、単語の区切りとして扱われIFSます。空白がデフォルトの単語区切りだからといって、この 2 つを混同しないでください。bash:

于 2012-10-17T12:46:27.047 に答える
2

:区切り文字です。a:bと に分かれてaおりb、その間には何もありません。予想される動作では、次のコードをどのようにエンコードしますか?

[a]
[]
[b]

唯一の奇妙な点は、末尾に 3 つの空の文字列がないことです。これが原因かもしれません

値を持たないパラメーターの展開の結果として生じる、引用符で囲まれていない暗黙の null 引数は削除されます。

于 2012-10-17T11:41:40.420 に答える
2

ケース2では、あなたが":a::b:c:::"IFS=:
ていることは、それぞれの文字列を分割することです:

:したがって、文字列の最初から、何":
ない最初の文字列まで、したがって[]

したがって、最初:から次までは です::a:
a[a]

そこから次へ:あなたが持っている::
ものは何もない、したがって[]

:そこから次:b:
b[b]

:そこから次:c:
c[c]

そこから次へ:あなたが持っている::
ものは何もない、したがって[]

そこから次へ:あなたが持っている::"
ものは何もない、したがって[]

だからあなたはその結果を得る..


@Mark Reedがコメントで言及したように、printf
一緒に使用できbash -xます:

$ bash -x
$ IFS=':'; var=':a::b:c:::'; printf "[%s]\n" $var
[12]+ IFS=:
[12]+ var=:a::b:c:::
[12]+ printf '[%s]\n' '' a '' b c '' ''     # notice this
[]
[a]
[]
[b]
[c]
[]
[]
于 2012-10-17T11:52:50.767 に答える
1

理由は非常に簡単です。

IFS=" "
var=" a  b c   "

output_args_one_per_line $var

これはoutput_args_one_per_line、次の引数で呼び出されることを意味します。

output_args_one_per_line  a  b c   

コマンド ラインの解析中に、BASH は追加の空白を削除するため、実際の呼び出しでは

output_args_one_per_line a b c

つまり、複数のスペースが 1 つにマージされます。前aのスペースは、コマンドと最初の引数の間のスペースになります。

つまり、適用される前に IFSスペースがなくなるということです。それはまた、あなたが書くことができないことを意味します

IFS=:
output_args_one_per_line:$var

コマンドの後には、単語区切りではなく、空白が必要です。

でスクリプトを実行するとset -x、トレース出力 (つまり、BASH がどのように行を展開するか) を確認できます。

2 番目のケースでは、区切り文字はスペース文字ではないため、コマンドと最初の引数の間に必要な空白は引数とマージされず、行は次のようになります。

output_args_one_per_line :a::b:c:::

唯一の奇妙な点は、出力の後に 3 つの空の引数cが表示されることですが、これはおそらく、空の末尾の引数が削除されるためです (BASH が引数の後の空白を削除するのと同じように)。別の奇妙な出力を次に示します。

IFS=:
var=":a::b:c::: "   # Blank after C
> output_args_one_per_line $var
[]
[a]
[]
[b]
[c]
[]
[]
[ ]

したがってvar、最後のコロンの後に何かが含まれている場合、不足している引数が取得されます。

于 2012-10-17T15:08:44.380 に答える