readarray(またはパイプ)の問題


19

私はreadarrayコマンドの奇妙な振る舞いに固執しました。

man bash状態:

readarray
     Read lines from the standard input into the indexed array variable array

しかし、これらのスクリプトは機能しません(配列は空です):

unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]}
unset arr; cat /etc/passwd | readarray arr;  echo ${#arr[@]}

そして、これらの仕事:

unset arr; readarray arr < /etc/passwd ;  echo ${#arr[@]}
unset arr; mkfifo /tmp/fifo; (echo a; echo b; echo c) > /tmp/fifo & mapfile arr < /tmp/fifo ; echo ${#arr[@]}

パイプの何が問題なのですか?

回答:


15

たぶん試してみてください:

unset arr
printf %s\\n a b c | {
    readarray arr
    echo ${#arr[@]}
}

うまくいくと思いますが、パイプラインの最後にある最後の{シェル; }コンテキストから出ると|、変数値が失われます。これは、パイプライン内の|個別の|プロセスがそれぞれサブシェルで|実行されるためです。あなたのことは同じ理由で機能しません:()

( arr=( a b c ) ) ; echo ${arr[@]}

...しません-変数値は、呼び出したものとは異なるシェルプロセスで設定されました。


23

readarray現在のシェルでコマンドが実行されるようにするには、パイプラインの代わりにプロセス置換を使用します。

readarray arr < <( echo a; echo b; echo c )

または(bash4.2以降の場合)lastpipeシェルオプションを使用します。

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr

1
クール。これは機能しますが、プロセス置換とは正確には何ですか?そして、< <2本の矢があるとはどういう意味ですか?
CMCDragonkai 14

1
bashmanページを参照してください。つまり、パイプラインをファイル記述子として扱うための構文です。内部のコマンドの出力からの< <(...)入力(最初の<)をリダイレクトすることを意味します<(...)。同様に、> >(...)内部のパイプラインの標準入力に標準出力を渡し>(...)ます。必ずしもプロセス置換でリダイレクトを使用する必要はありません。cat <( echo a b c )同様に動作します。
chepner

これらのオプションはどちらも、各配列項目が各文字列の末尾の行末を保持するという望ましくない結果をもたらします。一方、smac89による答えにはこの問題はありません。
thnee

3

readarray また、stdinから読み取ることができます。

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.