位置パラメータの単語スプレー

位置パラメータの単語スプレー

次の例を考えてみましょう。

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つではないことを発見するので、args3つの引数を持つ単純なコマンドです。スペースの大きさはあまり違いはありません。スペースだけでなくタブも含まれており、一部のシェル(たとえば、または)では何でも考慮されます。a:byashbashスペースあなたのロケールで(あなたの場合は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がループの条件で実行されるように合計に変換します。tededtfoowhile

噴射はいいえ解析の一部です。これは引数(forループワード、配列、および一部のシェルのリダイレクト先となります。その他の状況) 引用しない部分について説明します。もっと混乱するのはもう終わったことだ。暗黙的に。あなたはそれをしないでcmd split($x)、あなたはそれをしcmd $x、そしてsplit()実際にglob(split()))は暗黙的です。では、パラメータ拡張が存在する場合はzsh明示的に要求する必要があります(ハサミの形)。split($x)$=x$=

さて、例えば次のようになります。

args(){ echo ["$*"];}
args a   :b  # three spaces
# [a::b]

a最初の文字が提供される:bJoin引数(ワイルドカード演算子なので、ここで使用することはお勧めできません)。args$IFSa::b[...]

args(){ echo [$*];}
args a   :b  # three spaces
# [a  b]     # two spaces

$*(含む)は、空の文字列とa::bに分割されます。だからこれは:ab

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つは$IFSnullの場合です。

存在する:

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>失われることがわかります。ab$var


1 もちろん、単語を区別するのはスペースだけではありません。シェル構文の特殊トークンも使用でき、そのリストは状況によって異なります。ほとんどの場合、、、、、改行文字、、、、...は単語を区切り|ます。たとえば、次のように空白のないコマンドを作成できます。||&;<>>>ksh93

while({([[(:)]])})&&((1||1))do(:);uname<&2|tee>(rev)file;done

関連情報