私が知る限り、Bourneシェルと派生クラスではIFS=
IFSがnullに設定され、シェルはフィールド分割を行いません。
私は読んだことを覚えています:
echo "$*"
IFS= echo "$*"
uname -o
これら2つのコマンドをCentOSで1回、WSLで1回(= GNU / Linuxに固有のものであるため、ディストリビューションが不明)実行すると、空白行のみが表示されます。
上記のテストコマンドは何を意味し、これが実際にIFS学習の良い例ですか(そうでない場合は、どのような簡単な2行テストを提案しますか?)。
答え1
答える前に警告があります。変化はIFS
しばしば非常に混乱した結果を招く可能性があります。比較的安全で明確な効果(たとえば、read
同じコマンドを設定するなどIFS= read -r line
)がある場所がありますが、IFS=, read -r field1 field2 field3
一般的な動作を理解しようとするのは価値があるよりも多くの作業です。また、これを変更する場合は、前に割り当てを付けて特定のコマンドに分割するか(再度示すように)IFS= read -r line
変更する必要がある場合は、直ちに通常のコマンドに設定してください。
今問題は次のとおりです。これは効果の良いIFS
例ではありません。まず、$*
現在の引数リストに展開され、対話型シェルには通常引数がないため、空の文字列に展開されるためです。set
必要に応じてコマンドを使用して変更できます。例は次のとおりです。
$ echo "$*"
$ set -- "foo bar" "baz/quux"
$ echo "$*"
foo bar baz/quux
第二に、IFS
プレフィックスを特定のコマンドに変更すると(そのようにIFS= echo "$*"
)、そのコマンドが実行されたときにのみ影響し、シェルが引数を拡張するときは発生しません。今後コマンド自体)、echo
それ自体は影響を受けませんIFS
(IFS
設定に関係なく、常に引数を空白で付けます)。たとえば、
$ IFS= echo "$*" # No effect, because IFS is only set for echo, which ignores it
foo bar baz/quux
これをIFS
シェル自体の設定と比較します。
$ saveIFS=$IFS # Save the normal IFS, so we can set it back later
$ IFS= # Set IFS for the entire shell
$ echo "$*" # Now we'll see an effect
foo barbaz/quux
$ IFS='+-*/' # Let's try another value
$ echo "$*" # Now the arguments get merged, first char of IFS beween them
foo bar+baz/quux
$ echo $* # See below
foo bar baz quux
$ printf '%s\n' $* # See below
foo bar
baz
quux
$ IFS=$saveIFS # Set it back to normal, to avoid trouble later
それでは、「+-*/」が表示されたらecho $*
どうなりますか?IFS
まあ、IFS
彼らはすべてマージに使用されます。そして引数を分割するので with と同様にecho "$*"
ビット$*
は に拡張されますがfoo bar+baz/quux
二重引用符で囲まれていないので、すぐに単語に分割されます(みんな)IFS
なので、「foo bar」、「baz」、「quux」の3つの引数に分割し、その間にスペースを入れてすべてecho
一緒echo
に貼り付けます。デフォルトでは、このコマンドでも同じことが起こりますprintf
。ただし、フォーマット文字列のため、次の各引数は別々の行に印刷されるため、「foo bar」は1つの引数にすぎません。
그런데 어떤 사람들은 saveIFS
내가 여기서 사용하는 것과 같은 방법을 사용하고, 어떤 사람들은 unset IFS
쉘이 작동하게 만드는 이후에 사용하는 것을 선호합니다.마치 IFS
일반 space-tab-newline 값으로 되돌립니다. 둘 다 작동하지만함께 있지 않다. 나중에 저장하고 복원하려고 하면 unset IFS
빈 문자열로 설정되어 상황이 이상해집니다. 다음을 IFS=$' \t\n'
사용하여 명시적으로 재설정할 수도 있습니다.진짜지원되지 않는 쉘에서는 이상한 효과가 발생할 수 있습니다 $' '
.) 한숨을 쉬다.
편집 : 참조이 문제값을 저장하고 복원하는 방법에 대한 추가 옵션 및 토론 IFS
.
BTW2, 대부분의 경우 매개변수를 병합하거나 분할하는 것을 원하지 않으므로 원하는 것은 과 "$@"
달리 매개변수를 병합하지 않으며 큰따옴표를 사용할 때 매개변수를 분할하지 않습니다(또는 확장됩니다). 파일 이름 와일드카드) - 그냥 직접 전달합니다. 그러나 을 사용하지 마십시오 . 실제로는 이렇게 병합하기 때문입니다 (또는 쉘에 따라 첫 번째 문자 대신 ""를 사용하여 병합할 수도 있음 )(일반 변수에 저장하려면 병합해야 함). 대신 을 사용하여 배열로 저장하세요.$*
$@
args="$@"
"$*"
IFS
args=("$@")