readarray(或管道)问题

dch*_*kov 23 bash pipe

我坚持一种奇怪的readarray命令行为。

man bash状态:

readarray
     Read lines from the standard input into the indexed array variable array
Run Code Online (Sandbox Code Playgroud)

但这些脚本不起作用(数组为空):

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

这些工作:

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[@]}
Run Code Online (Sandbox Code Playgroud)

管道有什么问题?

che*_*ner 31

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

readarray -t arr < <( echo a; echo b; echo c )
Run Code Online (Sandbox Code Playgroud)

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

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray -t arr
Run Code Online (Sandbox Code Playgroud)

  • 凉爽的。这是可行的,但进程替代到底是什么?有 `&lt; &lt;` 2 个箭头是什么意思? (3认同)
  • 请参阅“bash”手册页。简而言之,它是将管道视为文件描述符的语法。`&lt; &lt;(...)` 表示从 `&lt;(...)` 内的命令输出重定向输入(第一个 `&lt;`)。类似地,`&gt; &gt;(...)` 会将标准输出传递给 `&gt;(...)` 内管道的标准输入。您不一定需要将重定向与进程替换一起使用。`cat &lt;( echo abc )` 也能工作。 (2认同)

mik*_*erv 17

也许尝试:

unset arr
printf %s\\n a b c | {
    readarray arr
    echo ${#arr[@]}
}
Run Code Online (Sandbox Code Playgroud)

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

( arr=( a b c ) ) ; echo ${arr[@]}
Run Code Online (Sandbox Code Playgroud)

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


sma*_*c89 5

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

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
Run Code Online (Sandbox Code Playgroud)