2016-03-11 2 views
-1

Я хочу построить список слов с помощью следующего сценария Баша, но добавлять не работает:Bash скрипт не добавляя

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

+0

Ваш вход. Кроме того, это не работает, потому что вы назначаете значения в подоболочке, я бы нашел дубликат, но я, честно говоря, не могу беспокоиться. Используйте 'while read blah, do blah, done 123

ответ

5

Вы попали в классическую проблему, связанную с трубами - каждая сторона трубы выполнена в своей подоболочке, поэтому используемый вами массив выходит из сферы действия, и его содержимое исчезает после петля.

Ваша проблема может быть решена просто (и вы избавляетесь от бесполезного использования 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

Ответ Тома Фенек хорошо, учитывая ваш случай использования и проблемы, однако вы также можете создать массив с помощью 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, чтобы избежать нежелательных побочных эффектов.