プラットフォームCentOSのLinuxは、bashで働いて、1810年6月7日にリリースします。GNUのbashの、バージョン4.2.46(2)-release(x86_64の-のRedHat-LinuxベースのGNU)
これは私が関数から複数の値を返すために、一般的に、特にbashの内のテキストを解析するための推奨を見てきましたイディオムです。
IFS=":" read A B <<< $(echo ONE:TWO)
私は、関数を呼び出すとき、私は予期しない動作を取得していYYYここの例では
IFS=":" read Y1 Y2 <<< $(yyy)
どこYYY自体も同様の呼び出しを行うことを望んでいます。
効果があるということ、私は明示的にIFSを指定するにもかかわらず、yyyは()内
IFS=":" read C1 C2 <<< $( echo "A:B" )
それは値「A B」を取得し、フィールドが解析され、両方の値はC1に割り当てられます。関数が単独で呼び出された場合、期待どおりには動作します。
これは、はるかに大きいスクリプトからダウン蒸留テストケース、です。私はここでIFSで何が起こっているか知りたいです。何らかの形で集約される結果フィールド原因発呼者に:「」失敗ケース(以下第二の例)にIFSを=設定します。予想通り仕事、出力以下第一及び第三の呼び出しは、YYYに()のコードの後に示します。
#!/bin/bash
debug() { echo "$1" 1>&2 ; }
yyy() {
debug "in yyy"
# why are the two values assigned to A here if the caller specified IFS?
IFS=":" read A B <<< $(echo ONE:TWO)
debug "A=$A"
debug "B=$B"
echo "$A:$B"
}
# this works as expected
read Y1 Y2 <<< $(yyy)
echo -e "===\n"
# this cause the read in yyy() to aggregate
IFS=":" read Y1 Y2 <<< $(yyy)
echo -e "===\n"
# This is a workaround that enables yyy() to work correctly
# But why do I need to do this?
OUT="$(yyy)"
IFS=":" read Y1 Y2 <<< $(echo $OUT)
これが出力されます
in yyy
A=ONE B=TWO
===
in yyy
A=ONE TWO B=
===
in yyy
A=ONE B=TWO
第二の場合にように注意しA
た値を取得しますONE TWO
これはバグのようですbash-4.2
、ここで説明したようにはbash 4.2で正しく分割herestringsをIFS。その上記のバージョンで動作するはずです。
GNUのbashの、バージョン4.2.46(2) -これらはあなたが持っているものと同じバージョンの結果です。私は、関数を実行した場合にはyyy
(設定することで、デバッグモードでset -x
プロンプトで)。
++ IFS=:
++ read A B
+++ echo ONE:TWO
++ debug 'A=ONE TWO'
++ echo 'A=ONE TWO'
A=ONE TWO
++ debug B=
++ echo B=
B=
++ echo 'ONE TWO:'
上記のISは、デバッグモード出力からの出力の抜粋します。ときあなたが見ることができるようにecho ONE:TWO
コマンド置換の結果として印刷され、何の単語の分割は、ラインがデフォルトのいずれかの文字が含まれていないので、起こることが予想されていないIFS
値(空白/タブや改行を)
あなたが文字列全体を読んで期待されるように、IFS=:
文字列を分割し、各構成変数に値を入れると期待A
してB
、何とか:
文字が失われ、文字列がONE TWO
最初の変数の値として保存されます。
正しい挙動を示すGNUのbashで機能実行、バージョン4.4.12(1)の出力を見てください。
++ IFS=:
++ read A B
+++ echo ONE:TWO
++ debug A=ONE
++ echo A=ONE
A=ONE
++ debug B=TWO
++ echo B=TWO
B=TWO
++ echo ONE:TWO
たくさんのがありましたIFS
バージョン4.4.0に関連するバグまでのbash / CHANGES。だから、個人的な勧告は、あなたアップグレードすることでbash
、より最近の安定のいずれかにバージョンを。参照してください二つの変数に文字列を分割しようとすると、
バージョン4.4.0(1)に同様のバグ-release
あなたは期待しONE:TWO
たときに変更されていないことを$(..)
理由前述の理由のために展開されています。しかし、ここでは、あまりにも範囲を定める文字が失われ、変数がA
に設定されていますONE TWO
IFS=":" read A B <<< $(echo ONE:TWO)
echo "$A"
ONE TWO
驚くべきことに、上記のコードは、4.4.0(1)以前のリリースで動作するように使用される機能を壊し意味し、4.2.46(2)上で動作します。