次の例を考えてみましょう。
IFS=:
x="a :b" # three spaces
echo ["$x"] # no word splitting
# [a :b] # as is
echo [$x] # word splitting
# [a b] # four spaces
単語セパレータは、コロンで区切られた単語"a "
(3つの空白)とを識別し"b"
、その間echo
にあるスペースが単語を連結します。しかし、値を関数引数として
使用すると、結果を解釈するのが難しいことがわかりました。$x
args(){ echo ["$*"];}
args a :b # three spaces
# [a::b]
そして:
args(){ echo [$*];}
args a :b # three spaces
# [a b] # two spaces
$*
すべての位置引数の組み合わせの値に展開されます。また、IFS変数値の最初の文字はwhere"$*"
と同じです。"$1c$2"
c
args(){ echo ["$1"]["$2"]; }
args a :b # three spaces
# [a][:b]
そして:
args(){ echo [$1][$2]; }
args a :b # three spaces
# [a][ b]
引用符のない拡張がある場合は、常にトークン化を実行する必要があります。ここで"$1"
、合計は同じで、$1
どちらの場合も:
区切り文字を使用しません。[$2]
->[ b]
両方はわからない。
おそらく、IFS分割を適用する前に他のトークン化ルールが使用されますが、見つかりません。
答え1
トークン化は、最新のBourne様シェルで引用符なしの拡張(引数拡張、算術拡張、およびコマンド置換)でのみ機能します(zsh
エミュレーションモードを使用しない限り、コマンド置換のみ可能)。
これを行うとき:
args a :b
まったく関連する噴射はありません。
シェル解析はこれをトークン化し、最初のものがキーワードの1つではないことを発見するので、args
3つの引数を持つ単純なコマンドです。スペースの大きさはあまり違いはありません。スペースだけでなくタブも含まれており、一部のシェル(たとえば、または)では何でも考慮されます。a
:b
yash
bash
スペースあなたのロケールで(あなたの場合はbash
マルチバイトではありません)。
Bourneシェルでも、トークン化は引用符なしのコマンド引数に適用され、拡張結果であるかどうかにかかわらず実行されます。上(後で)トークン化と解析。
Bourneシェルでは
IFS=i
while bib=did edit foo
そうではありません分析する今すぐ:
"wh" "le b" "b=d" "d ed" "t foo"
ただし、まずwhile
単純なコマンドとして、edit
その単純なコマンドの単語(bid=did
割り当てられた単語ではなくパラメータであるため)は次のようになります。もっと遠く引数が3つのコマンドの場合、合計ed
がループの条件で実行されるように合計に変換します。t
ed
ed
t
foo
while
噴射はいいえ解析の一部です。これは引数(for
ループワード、配列、および一部のシェルのリダイレクト先となります。その他の状況) 引用しない部分について説明します。もっと混乱するのはもう終わったことだ。暗黙的に。あなたはそれをしないでcmd split($x)
、あなたはそれをしcmd $x
、そしてsplit()
(実際にglob(split())
)は暗黙的です。では、パラメータ拡張が存在する場合はzsh
明示的に要求する必要があります(ハサミの形)。split($x)
$=x
$=
さて、例えば次のようになります。
args(){ echo ["$*"];} args a :b # three spaces # [a::b]
a
最初の文字が提供される:b
Join引数(ワイルドカード演算子なので、ここで使用することはお勧めできません)。args
$IFS
a::b
[...]
args(){ echo [$*];} args a :b # three spaces # [a b] # two spaces
$*
(含む)は、空の文字列とa::b
に分割されます。だからこれは:a
b
echo '[a' '' 'b]'
args(){ echo ["$1"]["$2"]; } args a :b # three spaces # [a][:b]
噴射がないので驚くべきことではありません。
args(){ echo [$1][$2]; } args a :b # three spaces # [a][ b]
これは次のとおりです。
echo '[a]' '[' 'b]'
as $2
(:b
)は空の文字列とに分割されますb
。
実装間の違いを確認できる状況の1つは$IFS
nullの場合です。
存在する:
set a b
IFS=
printf '<%s>\n' $*
一部のシェル(ほとんどの場合)では、次のものが表示されます。
<a>
<b>
<ab>
これらの"$*"
拡張にもかかわらず、ab
これらのシェルは依然としてこれらのパラメータを位置パラメータa
とは別に維持します。b
これは現在のバージョンの標準のPOSIX要件です。
これにより:
set a b
IFS=
var="$*" # note that the behaviour for var=$* is unspecified
printf '<%s>\n' $var
に割り当てると、2つの別々のパラメータに関する情報が<ab>
失われることがわかります。a
b
$var
1 もちろん、単語を区別するのはスペースだけではありません。シェル構文の特殊トークンも使用でき、そのリストは状況によって異なります。ほとんどの場合、、、、、改行文字、、、、...は単語を区切り|
ます。たとえば、次のように空白のないコマンドを作成できます。||
&
;
<
>
>>
ksh93
while({([[(:)]])})&&((1||1))do(:);uname<&2|tee>(rev)file;done