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

管道有什么问题?

Answers:


15

也许尝试:

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

我希望它会起作用,但是当您在管道末端退出最后一个{shell ; }上下文时,|您将丢失变量值。这是因为管道中每个|单独的|进程|都在(subshel​​l中执行)。因此,您的事情由于相同的原因而无法正常工作:

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

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


23

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

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

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

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

1
凉。这可行,但是流程替代到底是什么?拥有< <2个箭头意味着什么?
CMCDragonkai 2014年

1
请参见bash手册页。简而言之,它是将管道视为文件描述符的语法。< <(...)意味着<从里面的命令输出重定向输入(第一个)<(...)。类似地,> >(...)会将标准输出传递到内部管道的标准输入>(...)。您不一定需要将重定向与进程替换一起使用。cat <( echo a b c )也可以。
chepner

这两个选项都对我产生不利的结果,其中每个数组项都将行末尾保留在每个字符串的末尾。而smac89的答案不存在此问题。
thnee

3

readarray 也可以从stdin中读取,因此:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.