Bash脚本没有追加

时间:2016-03-11 10:54:52

标签: bash

我想用以下bash脚本构建一个单词列表但是append不起作用:

declare -a NODES=()
cat $1 | while read line;do
    for word in $line; do
       NODES+=("$word")
       echo $word
    done
done

echo "Nodes: ${NODES[@]}"

我得到了输出:

 node01
 node02
 node03
 node04
 Nodes:

运行脚本:

 $ bash myscript.sh nodes_list

nodes_list文件:      NODE01      NODE02      node03      node04

2 个答案:

答案 0 :(得分:5)

你遇到了一个与管道有关的经典问题 - 管道的每一面都在它自己的子shell中执行,所以你使用的数组超出范围,其内容在循环后消失。

你的问题可以简单地解决(你也摆脱了对cat无用的使用):

nodes=() # no need to use declare here, use lowercase variable names
while read -r line; do # -r switch is almost always what you want
    for word in $line; do
       nodes+=("$word")
       echo "$word" # always quote your variables!
    done
done < "$1" # use redirection instead of a pipe to avoid creating a subshell

echo "Nodes: ${nodes[@]}"

答案 1 :(得分:1)

根据您的用例和问题,Tom Fenech的答案很好,但您也可以使用IFS创建一个数组:

#!/bin/bash
declare nodes=( $(<"$1") )

for (( i = 0; i < ${#nodes[@]}; ++i )); do
  echo "line: ${i}: ${nodes[$i]}"
done

将之前的代码保存为toto.bash,它将回显:

$ ./toto.bash toto.bash
line: 0: #!/bin/bash
line: 1: declare
line: 2: nodes=(
line: 3: $(<"$1")
line: 4: )
line: 5: for
line: 6: ((
line: 7: i
line: 8: =
line: 9: 0;
line: 10: i
line: 11: <
line: 12: ${#nodes[@]};
line: 13: ++i
line: 14: ));
line: 15: do
line: 16: echo
line: 17: "line:
line: 18: ${i}:
line: 19: ${nodes[$i]}"
line: 20: done

如果你需要逐行分割(例如:获取包含每一行的数组),你可以这样做:

OIFS=$IFS
IFS=$'\n'
declare nodes=( $(<"$1") )
IFS=$OIFS

OIFS用于恢复之前的IFS,以避免不必要的副作用。