2013-08-23 5 views
0

Вот простая команда, которую я запускаю в bash, но массив выиграл; t по какой-то причине заселен.Ошибка заполнения массива Bash

array=() && sudo iwlist wlan0 scan | grep 'Address'| while read line; do array[${#array[@]}]=$line; done 

Я также попытался заполнить массив следующим образом:

array=() 
sudo iwlist wlan0 scan | grep 'Address'| while read line; do array+=($line); done 

, но это дает мне тот же результат. Я знаю, что это работает, потому что, когда я это сделать:

sudo iwlist wlan0 scan | grep 'Address'| while read line; do "echo $line"; done 

он будет печатать каждую строку, которая передается по конвейеру от Grep на время цикла.

Когда я проверяю размер массива «echo $ {# array [@]», он покажет 0, и если я напечатаю массив, он, очевидно, ничего не напечатает. Вы видите ошибки в строке?

** ОБНОВЛЕНИЕ. Я получил это работает, используя для цикла следующим образом:

for line in $(sudo iwlist wlan0 scan | grep 'Address' -A5); do array+=($line); done 

ответ

3

BASH FAQ вход # 24: "I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?"

Петля в то время как [...] выполнен в новом субоболочке со своей собственной копией переменной [...]

Используйте следующие в качестве обходного пути:

while read line; 
    do array+=("$line") 
done < <(sudo iwlist wlan0 scan | grep 'Address') 
+0

Даже подумал, что я использовал bash в течение длительного времени, я не знал этого, так как всегда использовал, когда читал для печати данные напрямую, без необходимости хранить его в любом месте. В любом случае, я решил свою проблему, используя цикл for так: for line in (sudo iwlist wlan0 scan | grep 'Address'); do array + = ($ line); сделанный. Cheers – JohnnyLoo

+0

@JuanCarlos Использование цикла 'for' не является хорошей идеей, так как расширенные значения в' $() 'будут открыты для расширения пути и иногда будут давать вам разные значения для' $ line'. Это также заставляет bash выделять большой буфер для всего вывода сначала перед чтением каждой строки, что не очень хорошо для больших выходов по сравнению с чтением с 'while'. – konsolebox

+0

Отлично, что отлично работает. Спасибо чувак – JohnnyLoo

1

Попробуйте использовать процесс замены вместо:

array=() 
while read line; do array+=($line); done < <(exec sudo iwlist wlan0 scan | grep 'Address') 

Или используйте lastpipe вариант:

shopt -s lastpipe 
array=() && sudo iwlist wlan0 scan | grep 'Address'| while read line; do array[${#array[@]}]=$line; done 

Это также дешевле использовать readarray или mapfile, если вы используете Bash 4.0+. Нет необходимости инициализировать array с () и нужно только обновить, если ранее он был объявлен другим типом в более глобальном контексте.

readarray -t array < <(exec sudo iwlist wlan0 scan | grep 'Address') 

shopt -s lastpipe 
sudo iwlist wlan0 scan | grep 'Address' | readarray -t array 
Смежные вопросы