readarray(或管道)问题

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

水管出了什么问题?

答案1

要确保readarray命令在当前 shell 中执行,请使用进程替换代替管道:

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

或者(如果是bash4.2 或更高版本)使用lastpipeshell 选项:

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

请注意,默认情况下,第二种方法lastpipe在交互式会话中不起作用。在这种情况下,首先运行

set +m

禁用“监视模式”。

答案2

也许尝试:

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

我预计它会起作用,但是当您走出管道末尾的最后一个{shell上下文时,您将丢失变量值。这是因为管道中的每个单独进程都在子 shell中执行。所以你的东西因为同样的原因不起作用:; }||||()

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

...不 - 变量值设置在不同的shell 进程而不是您调用它的进程。

答案3

readarray也可以从 stdin 读取,所以:

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

相关内容