我可以让这个在ksh中工作,但不是在bash中,这真的让我疯了.
希望这是我忽略的显而易见的事情.
希望这是我忽略的显而易见的事情.
我需要运行一个外部命令,其中输出的每一行都将存储在数组索引中.
这个简化的例子看起来是正确地在循环中设置数组但是在循环完成后这些数组赋值消失了?好像循环被完全视为外壳?
junk.txt
this is a test to see if this works ok
testa.sh
#!/bin/bash declare -i i=0 declare -a array echo "Simple Test:" array[0]="hello" echo "array[0] = ${array[0]}" echo -e "\nLoop through junk.txt:" cat junk.txt | while read line do array[i]="$line" echo "array[$i] = ${array[i]}" let i++ done echo -e "\nResults:" echo " array[0] = ${array[0]}" echo " Total in array = ${#array[*]}" echo "The whole array:" echo ${array[@]}
产量
Simple Test: array[0] = hello Loop through junk.txt: array[0] = this is a array[1] = test to see array[2] = if this works ok Results: array[0] = hello Total in array = 1 The whole array: hello
因此,在循环中,我们分配array [i]并且echo验证它.
但是在循环之后我回到了包含“hello”的数组[0]而没有其他元素.
bash 3,4和不同平台的结果相同.
因为while循环位于管道中,所以循环体中的所有变量赋值都是执行循环的子shell的本地. (我相信ksh不会在子shell中运行命令,这就是你在bash中遇到问题的原因.)这样做:
while read line do array[i]="$line" echo "array[$i] = ${array[i]}" let i++ done < junk.txt
很少,如果有的话,你是否想用cat将一个文件传递给另一个命令;改为使用输入重定向.
更新:因为您需要从命令而不是文件运行,另一个选项(如果可用)是进程替换:
while read line; do ... done < <( command args ... )
如果进程替换不可用,则需要输出到临时文件并从该文件重定向输入.
如果您使用的是bash 4.2或更高版本,则可以在循环之前执行这两个命令,并且原始的pipe-into-the-循环将起作用,因为while循环是管道中的最后一个命令.
set +m # Turn off job control; it's probably already off in a non-interactive script shopt -s lastpipe cat junk.txt | while read line; do ...; done
更新2:这是一个基于user1596414评论的无循环解决方案
array[0]=hello IFS=$'\n' array+=( $(command) )
您的命令输出将分为仅基于换行符的单词(以便每行都是一个单独的单词),并将生成的每插槽行数附加到原始行.如果您只使用循环来构建数组,这非常好.它也可能被修改以容纳少量的每行处理,模糊地类似于python列表理解.