
Bashでは、以下があると仮定しますvar=a.b.c.
。
$ IFS=. printf "%s\n" $var
a.b.c
ただし、これらの使用法はIFS
配列を作成するときに適用されます。
$ IFS=. arr=($var)
$ printf "%s\n" "${arr[@]}"
a
b
c
もちろんとても便利ですが、これはどこに記録されるのでしょうか?次の章をすばやく読んでください。ソートまたは噴射Bash ドキュメントには指示はありません。IFS
貫通して見てシングルページ文書この効果のヒントも提供されません。
これはいつ安定して実行できるのかわかりません。
IFS=x do something
そして、これはIFS
フィールド分割に影響を与えると予想されます。
答え1
基本的なアイデアは、外部コマンドが実行されたときに実行されるようにVAR=VALUE some-command
設定することであり、それよりもクールではありません。これらの直観をシェルの仕組みに関する知識と組み合わせることで、ほとんどの場合正しい答えを得ることができます。 POSIX 参照は次のとおりです。VAR
VALUE
some-command
some-command
「シェルコマンド言語」の章の「簡単なコマンド」。
もしsome-command
あれば外部コマンド、VAR=VALUE some-command
と同じですenv VAR=VALUE some-command
。VAR
は環境にエクスポートされ、some-command
シェルの値(または値不足)は変更されません。
もしsome-command
あれば機能、それとVAR=VALUE some-command
同じですVAR=VALUE; some-command
。つまり、クォータがまだ存在する関数が返された後、変数は環境にエクスポートされません。その理由は、Bourneシェルの設計(およびそれ以降の下位互換性)に関連しています。関数の実行中に変数の値を保存および復元する機能はありません。関数はシェル自体で実行されるため、変数をエクスポートしないことをお勧めします。ただし、ksh(ATT ksh93およびpdksh / mkshを含む)、bash、およびzshは、VAR
関数の実行中にのみ設定されるより便利な動作を実装します(エクスポートもあります)。存在するケシfunction NAME …
、標準構文を使用して定義された関数ではなく、ksh構文を使用して関数が定義されている場合は、これを行いますNAME ()
。存在する強く打つこれは、POSIXモード(ランタイム使用時)ではなくbashモードでのみ行われますPOSIXLY_CORRECT=1
。存在する扱いにくいposix_builtins
、このオプションが設定されていない場合、このオプションはデフォルトでは設定されていませんが、またはemulate sh
で設定できますemulate ksh
。
組み込み関数の場合、some-command
動作は組み込み関数のタイプによって異なります。特殊組み込み機能関数のように動作します。特別な組み込み機能は、シェルの状態に影響を与えるため(たとえば、break
制御フローに影響、cd
現在のディレクトリに影響、set
位置パラメータ、およびオプションに影響を与えるため)、シェル内で実装する必要があります。その他の内蔵機能組み込み機能はパフォーマンスと利便性のためのものであり(ほとんど - たとえば、bash機能は組み込みprintf -v
機能としてのみ実装できます)、外部コマンドのように機能します。
エイリアス拡張後に割り当てが発生するため、ifsome-command
は次のようになります。ニックネーム、最初に展開して何が起こるかを確認してください。
すべての場合において、割り当てはコマンドライン自体の変数置換を含むコマンドラインを解析した後に行われます。そのため、課題の前に評価が行われるのでvar=a; var=b echo $var
印刷されます。したがって、以前の値を使用して分割します。a
$var
IFS=. printf "%s\n" $var
IFS
$var
すべてのタイプのコマンドに対処しましたが、状況がもう1つあります。実行するコマンドがありません。つまり、コマンドに割り当て(およびリダイレクトも可能)のみが含まれている場合です。この場合、クォータがまだ存在する。VAR=VALUE OTHERVAR=OTHERVALUE
と同じですVAR=VALUE; OTHERVAR=OTHERVALUE
。したがって、その後もIFS=. arr=($var)
まだにIFS
設定されています.
。$IFS
課題では〜を使用でき、arr
その課題にはすでに新しい値があると予想できるため、拡張にIFS
新しい値を使用することは合理的です$var
。
簡単に言えば、IFS
使えます一時的なフィールド分割のみ:
- 新しいシェルまたはサブシェルを起動します(たとえば、値に2文字未満の文字が含まれている場合は動作が異なることを除いて、これは
third=$(IFS=.; set -f; set -- $var; echo "$3")
複雑なアプローチです)。third=${var#*.*.}
var
.
- kshでは、withはksh構文を使用して定義され
IFS=. some-function
ます。some-function
function some-function …
IFS=. some-function
Bashとzshでは、互換モードではなくデフォルトモードで実行されている限り。
答え2
@Gillesの答えは本当に素晴らしいです。彼は複雑な問題を詳しく説明しています。
しかし、私はこのコマンドがなぜ必要なのかという答えを信じています。
$ IFS=. printf "%s\n" $var
a.b.c
仕組みは簡単です。完全なコマンドラインは次のとおりです。以前に解析済み実行されました。各「単語」はシェルによって一度処理されます。
これたとえば、操作がIFS=.
遅れます。(4番目のステップは最後のステップです):
4.-各変数の割り当てを拡張する必要があります...
コマンドを実行する前に、引数のすべての拡張が最初に処理され、次の実行可能行が構築されます。
$ IFS=. printf "%s\n" a.b.c ## IFS=. goes to the environment.
a.b.c
コマンドに引数とが与えられる前に、値は$var
「古い」IFSに拡張されます。a.b.c
printf
"%s\n"
a.b.c
評価する
最初のレベルの待ち時間は、次の方法で導入できますeval
。
$ IFS=. eval printf "'%s\n'" \$var
a
b
c
その行は、「IFS =」を使用して(最初に)解析されます。環境は次のように設定されます。
$ printf '%s\n' $var
その後、次のように解決されます。
$ printf '%s\n' a b c
そしてこれを実行してください:
a
b
c
(abc)値は、$var
使用しているIFS値と区別されます.
。
環境
複雑でトリッキーな部分は、いつ、どのコンテキストで動作するかです!
Gilesの答えの最初の部分はこれを非常によく説明しています。
1つの追加の詳細があります。
このコマンドを実行するとき:
$ IFS=. arr=($var)
IFSの価値は現在の環境で維持されます。例:
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <.>
IFSは個々の明細書に使用されます。
ただし、次のような場合は回避できます。単一ステートメントの IFS 設定
$ IFS=. command eval arr\=\(\$var\)
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <
>
答え3
あなたの質問について
var=a.b.c
IFS=. printf "%s\n" $var
それは極端な状況です。
これはmacro expansion
、コマンドで発生するためです。今後シェル変数がIFS=.
設定されました。
つまり、$var
拡張すると、前のIFS
値がアクティブになり、次にIFS
設定されます'.'
。