web-dev-qa-db-ja.com

文字列を2つの変数に分割しようとしています

文字列を2つの変数に分割しようとしています(whileループを使用する必要はありません)。

var="hello:world"
IFS=':' read var1 var2 <<< $var

echo "var1: $var1"
echo "var2: $var2"

しかし、私は望ましい結果を得ていません:

var1: 'hello world'
var2: ''

この方法(または同様の方法)でそれを行うことが可能かどうか誰かが説明できますか?

13
coda

これはBash4.2のバグです。適切な説明については、 チェプナーの答え を参照してください。


それは引用についてです。使用する:

IFS=':' read var1 var2 <<< "$var"
                           ^    ^

の代わりに

IFS=':' read var1 var2 <<< $var

結果を参照してください:

$ IFS=':' read var1 var2 <<< "$var"
$ echo "var1=$var1, var2=$var2"
var1=hello, var2=world

だが

$ IFS=':' read var1 var2 <<< $var
$ echo "var1=$var1, var2=$var2"
var1=hello world, var2=

将来の読者のための参考:

これについて開発者と話し合ったところ、これは確かにbash 4.2のバグであり、次の4.3リリースで修正されているようです。 開発ブランチ変更ログ から

rrrr。 IFSが一時環境に表示され、リダイレクトで使用される場合のいくつかの問題を修正しました。

とにかくパラメータ展開を引用符で囲むことは常に良い考えですが、OPのコードは引用符なしで意図したとおりに機能するはずです。


これがバグの説明です。コードで

var="hello:world"
IFS=':' read var1 var2 <<< $var

引用符で囲まれていない$varは、IFSのグローバル値に文字が含まれていない(つまり、空白がない)ため、単一の単語である必要がありますreadには、文字列hello:worldが表示されます。 2つの引数を受け取ったため、ローカル値IFSを使用してワード分割を適用し、それぞれvar1var2に割り当てられるhelloworldを生成する必要があります。

バグは、here文字列がIFSの「リークされた」値をreadに渡して部分的に分割されているように見えることです。その結果、文字列はhello worldになりますが、それでもreadでは単一の単語として認識されます。その単語には:が含まれていないため、readはそれを2つの単語に分割せず、文字列全体がvar1に割り当てられます。

bash 4.3では、文書化されているように、$varの展開は、<<<演算子への引数としてWord分割を受けません。コード

var="hello:1:2 world"
IFS=: read var1 var2 <<< $var

var1helloに設定し、var21:2 worldに設定します。

11
chepner