Вложенный сценарий оболочки не работает с переменной списка

Как указано в здесь , файл wpa _supplicant.service предназначен для служб, поддерживающих DBus, поэтому он будет автоматически обнаружен, например, NetworkManager. Как я полагаю, вы не используете NetworkManager, вам нужно либо написать программу/скрипт, который будет использовать информацию DBus для поднятия интерфейса, либо использовать конкретную версию интерфейса wpa _supplicant@.service. Цитирование:

The wpa_supplicant package provides multiple systemd service files:

wpa_supplicant.service - uses D-Bus, recommended for NetworkManager users.

wpa_supplicant@.service - accepts the interface name as an argument and starts the wpa_supplicant daemon for this interface. It reads a /etc/wpa_supplicant/wpa_supplicant-interface.conf configuration file.

wpa_supplicant-nl80211@.service - also interface specific, but explicitly forces the nl80211 driver (see below). The configuration file path is /etc/wpa_supplicant/wpa_supplicant-nl80211-interface.conf.

wpa_supplicant-wired@.service - also interface specific, uses the wired driver. The configuration file path is /etc/wpa_supplicant/wpa_supplicant-wired-interface.conf.

Reference

0
26.01.2020, 22:32
3 ответа

В вашем коде нет переменной списка. У вас есть строка.

Вызов test1использует расширение $letterListбез кавычек. Это заставит оболочку разделить свое значение на несколько слов по пробелам, табуляциям и символам новой строки (по умолчанию ), и каждое слово будет подвергаться подстановке имени файла (, если оно содержит символы подстановки имени файла ). Результирующие слова передаются в test1как отдельные аргументы.

В test1вы помещаете только самый первый из этих аргументов в letterList.

Если вы хотите передать строку из $letterListкак есть в test1из test2, вам нужно заключить ее расширение в двойные кавычки в вызове:

test1 "$letterList"

Между прочим, вы полагаетесь на то, что оболочка выполняет разбиение $letterListзначения в вашем цикле вtest1(той же механике, которая вызывает вашу проблему ), но вы никогда не защищаете код от случайное выполнение подстановки имени файла (проверьте свой скрипт, например, test2 "A B C *"чтобы понять, что я имею в виду ).


Если вы хотите передать список , а не одну строку, вызовите test2со списком, а не со строкой:

test2 A B C "Hello World" "* *"

Затем в test2передайте аргументы вtest1:

#!/bin/sh

test1 "$@"

Здесь "$@"расширит список позиционных параметров (до аргументов скрипта ), при этом каждый отдельный параметр будет заключен в кавычки.Это означает, что такой аргумент, как Hello World, не будет разделен на несколько аргументов при вызове test1, и строка * *также не будет разделена на две части, и не произойдет подстановки имен файлов.

В test1перебрать аргументы:

#!/bin/sh

for arg in "$@"; do
    printf '%s\n' "$arg"
done

или

#!/bin/sh

for arg do
    printf '%s\n' "$arg"
done

... или, если вы просто хотите напечатать аргументы, просто

#!/bin/sh

printf '%s\n' "$@"

Я везде использовал /bin/shв качестве оболочки, так как здесь нет ничего специфичного для bash.

3
28.01.2020, 02:17

При запуске ./test2 'a b c'мы получаем:

$1=a b c

Таким образом, последняя строка становится:

test1 a b c

И когда запускается test1, мы получаем:

$1=a
$2=b
$3=c

То есть аргументы, передаваемые test1, не заключены в кавычки, и, следовательно, они становятся тремя аргументами, а не одним.

Чтобы передать test1один аргумент, просто заключите переменную в двойные кавычки. То есть замените последнюю строку в test2на:

./test1 "$letterlist"

Обратите внимание: я также добавил ./, чтобы указать путь к исполняемому файлу, поскольку не рекомендуется иметь .в $PATH.

1
28.01.2020, 02:17

Непонятно, какова ваша настоящая цель. Единственное, что вы ясно сказали, это то, что вы хотите test2 'A B C'для вывода A, Bи Cна трех отдельных строках.

Вот другое решение, которое даст вам такой результат. В целом, кажется, что он дает тот же результат, что и ответ Кайлума .

  • Оставьте test2прежним.
  • Измените test1следующим образом:

    #!/bin/sh
    
    for letter in $*
    do
        printf '%s\n' "$letter"
    done
    

    Это, естественно, меняет поведение test1. Теперь он рассматривает все свои аргументы, а не только $1. Таким образом, test1 'A B C' 'D E F'выведет A, B, C, D, Eи F. на шести отдельных строках (вместо просто A, Bи C).

Обычно мы не рекомендуем использовать $*, потому что он разбивает строки, содержащие пробелы, на отдельные слова. Например, "lazy dog"станет двумя словами (аргументы ). Но, кажется, это именно то поведение, которое вам нужно.

printfнемного безопаснее, чем echo, в случае, если имя файла начинается с-или содержит \. Это подробно обсуждалось на этом сайте; если вам нужна дополнительная информация, просто найдите ее.

0
28.01.2020, 02:17

Теги

Похожие вопросы