web-dev-qa-db-ja.com

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

パイプのどこがいけないの?

19
dchirikov

多分試してください:

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

うまくいくと思いますが、{pipelineの最後にある最後の; } Shell |コンテキストから抜けると、変数の値が失われます。これは、|pipeline内の|separate |プロセスのそれぞれが(subshel​​l)で実行されるためです。だからあなたのことは同じ理由でうまくいかない:

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

...そうではない-変数の値は、呼び出したプロセスとは異なり、異なるシェルプロセスで設定された.

15
mikeserv

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

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
26
chepner

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

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