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

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[@]} 

パイプの何が問題になっていますか?

回答

試してみてください:

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

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

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

…機能しません-変数値が異なる<に設定されました/ em>呼び出し元のシェルプロセスよりもシェルプロセス。

回答

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

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

または(bash 4.2以降)lastpipeシェルオプションを使用します:

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

コメント

  • かっこいい。これは機能しますが、プロセス置換とは正確には何ですか?また、< < 2つの矢印があるとはどういう意味ですか?
  • bashのマニュアルページを参照してください。つまり、パイプラインをファイル記述子として扱うための'の構文です。 < <(...)は、<(...)<)をリダイレクトすることを意味します>。同様に、> >(...)は、標準出力を>(...)内のパイプラインの標準入力に渡します。 'プロセス置換でリダイレクトを使用する必要は必ずしもありません。 cat <( echo a b c )も同様に機能します。
  • これらのオプションはどちらも、各配列項目が各文字列の末尾の行末を保持するという望ましくない結果をもたらします。 smac89による回答にはこの問題はありませんが、
  • readarray -t arrを使用して行末を削除できます。 man bashから:-t Remove a trailing newline from each line read.
  • 'で

5.0.17で、これは'私には機能しません。 'もBASHOPTSをチェックしましたが、lastpipeが含まれていますが、cat myfile.txt | readarray -t arrは空のarrを提供しますが、readarray -t arr < <(cat myfile.txt)は正しく機能します。

回答

readarrayはstdinからも読み取ることができるため、次のようになります。

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]} 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です