Команда не работает должным образом в скрипте оболочки

Команда не работает должным образом в скрипте оболочки

Вот вывод:

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null 
Яш Шах
CoreFragment
CoreFragment_5G
CoreFragment
длинк
Яш Шах
КОМФАСТ
Appbirds_Технологии
СИМБИОЗ
20096641
CoreFragment_5G
AMBER_AP1
REDWING LABS_5G

Хотя одно и то же, написанное в сценарии, работает по-разному.

Вот фрагмент, в котором я использовал указанную выше команду.

for ssid_name in $(sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null)
do
    echo "$ssid_name"
done

Я получил такой вывод:

Яш
Шах
CoreFragment
CoreFragment_5G
CoreFragment
Яш
Шах
КРАСНОЕ КРЫЛО
ЛАБОРАТОРИИ
КОМФАСТ
Appbirds_Технологии
СИМБИОЗ
CoreFragment_5G
КРАСНОЕ КРЫЛО
ЛАБОРАТОРИИ_5G

Примечание: Если в выводе есть пробел, он воспринимается как новая строка.

Я работаю на Ubuntu 18.04.

решение1

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

  1. Вывод sedподставляется (с помощью подстановки команды $(...)) после in;
  2. Полученная строка разворачивается в список элементов;
  3. Каждый элемент в свою очередь назначается ssid_nameи печатается echo.

Расширение в пункте 2 выполняется в соответствии со значением внутреннего разделителя полей ( IFS), которое по умолчанию равно <space><tab><newline>. Таким образом,ваше решениеработает, потому что позволяет forразбить заменяемую строку только по символам новой строки.

В качестве отступления от вашего ответа, обратите внимание, что $'\n'это непереносимо - даже если этот синтаксис ( $'string') поддерживается во многих оболочках.
Тем не менее, вы можете использовать такое назначение:

IFS='
'

Альтернативной конструкцией для обработки строк ввода является использование readв whileцикле:

sudo iwlist scan 2>/dev/null | grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null |
while IFS= read -r i; do
    printf '%s\n' "$i"
done

Здесь каждая строка sedвывода также разделяется в соответствии со значением IFS— которое в этом примере установлено как раз на нулевую строку, чтобы предотвратить любые эффекты разделения слов — но строки будут оставаться разделенными независимо readот IFS.

решение2

Лучше использовать whileпетлю с readвместо forпетли.

sudo iwlist scan 2>/dev/null |grep ESSID | sed 's/.*ESSID:"\(.*\)".*/\1/' 2>/dev/null | while IFS= read -r ssid_name
do
    echo $ssid_name
done

смотрите такжеhttps://mywiki.wooledge.org/BashFAQ/001

решение3

Добавив следующую строку в код перед циклом for, в моем случае все работает отлично.

МФС=$'\n'

Связанный контент