私は絶対に間違っているかもしれませんが、IFSをコマンドの1つとして設定することは私には説得力があるように見えます pre-do /doneリストにあるものはまったく効果がありません。
外部IFS(while
の外) コンストラクト)は、以下のスクリプトに示されているすべての例で優先されます。
何が起きてる?この状況でIFSが何をするかについて間違った考えを持っていますか?配列分割の結果は、「期待される」列に示されているとおりになると期待していました。
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- t --------tactual"
echo -e "outside t IFS tinside"
echo -e "loop t Field tloop"
echo -e "IFS NR NF t Split tIFS (actual)"
echo -e "----- -- -- t --------t-----"
IFS=$' tn'; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 1'; show "$REPLY"; done
IFS=$' tn'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't 2'; show "$REPLY"; done
IFS=$' tn'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne 't 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne 't 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne 't11'; show "$REPLY"; done
echo -e "----- -- -- t --------t-----"
出力:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
承認された回答:
(申し訳ありませんが、長い説明)
はい、IFS
while IFS=" " read; do …
残りのコードには影響しません。
まず、シェルコマンドラインが2種類の変数を備えていることを正確に説明しましょう。
- シェル変数(シェル内にのみ存在し、シェルに対してローカルです)
- すべてのプロセスに存在する環境変数。これらは通常、
fork()
で保持されます およびexec()
、したがって子プロセスはそれらを継承します。
次のコマンドを使用してコマンドを呼び出す場合:
A=foo B=bar command
コマンドは、(環境)変数A
が存在する環境内で実行されます。 foo
に設定されています およびB
bar
に設定されています 。ただし、このコマンドラインでは、現在のシェル変数A
およびB
変更されていない 。
これは次とは異なります:
A=foo; B=bar; command
ここで、シェル変数A
およびB
が定義され、コマンドが環境変数A
なしで実行されます およびB
定義されています。 A
の値 およびB
command
からアクセスできません 。
ただし、一部のシェル変数がexport
の場合 -edの場合、対応する環境変数はそれぞれのシェル変数と同期されます。例:
export A
export B
A=foo; B=bar; command
このコードでは、両方のシェル 変数とシェル環境 変数はfoo
に設定されます およびbar
。環境変数はサブプロセスに継承されるため、command
それらの値にアクセスできるようになります。
元の質問に戻るには、次の場所にあります:
IFS='a' read
read
のみ 影響を受けた。実際、この場合、read
IFS
の値は気にしません 変数。 IFS
を使用します 次のように、行を分割する(そしていくつかの変数に格納する)ように要求した場合のみ:
echo "a : b : c" | IFS=":" read i j k;
printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"
IFS
read
では使用されません 引数で呼び出されない限り。 (編集: これは正確には当てはまりません。IFS
に存在する空白文字、つまりスペースとタブ 入力行の最初/最後では常に無視されます。 )