Странное поведение с расширением параметров в аргументах программы - PullRequest
0 голосов
/ 19 декабря 2018

Я пытаюсь условно передать аргумент скрипту bash, только если он был установлен в вызывающем скрипте, и я заметил странное поведение.Я использую расширение параметра, чтобы облегчить это, выводя опцию, только если установлена ​​соответствующая переменная.Цель состоит в том, чтобы передать аргумент из родительского сценария в дочерний сценарий.

Рассмотрим следующий пример:

Вызывающий сценарий:

#!/bin/bash
# 1.sh

ONE="TEST_ONE"
TWO="TEST_TWO"

./2.sh \
    --one "${ONE}" \
    "${TWO:+"--two ${TWO}"}" \
    --other

и вызываемый скрипт:

#!/bin/bash
# 2.sh

while [[ $# -gt 0 ]]; do
    key="${1}"

    case $key in
        -o|--one)
        ONE="${2}"
        echo "ONE: ${ONE}"
        shift
        shift
        ;;
        -t|--two)
        TWO="${2}"
        echo "TWO: ${TWO}"
        shift
        shift
        ;;
        -f|--other)
        OTHER=1
        echo "OTHER: ${OTHER}"
        shift
        ;;
        *)
        echo "UNRECOGNISED: ${1}"
        shift
        ;;
    esac
done

output:

ONE: TEST_ONE
UNRECOGNISED: --two TEST_TWO
OTHER: 1

Обратите внимание на поведение опции '--two', которая будет не распознана.Похоже, что он расширяется правильно, но не распознается как две разные строки.Кто-нибудь может объяснить, почему это происходит?Я видел, что в одном источнике написано, что it will not work with positional parameter arguments, но я до сих пор не понимаю, почему это ведет себя так, как оно.

1 Ответ

0 голосов
/ 19 декабря 2018

Это потому, что когда вы передаете $2 в результате расширения параметра из 1.sh, вы цитируете его таким образом, что --two TEST_TWO оценивается как один единственный аргумент, так что количество аргументов в 2.shрезультат в 4 вместо 5

Но, тем не менее, использование вашего $2 в качестве ${TWO:+--two ${TWO}} решит проблему, но это разделит слово на содержимое $2, если оно содержит пробелы,Вам нужно использовать массивы.

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

argsList=(--one "${ONE}" ${TWO:+--two "${TWO}"} --other)

и передайте их как

./2.sh "${argsList[@]}"

или если вы знакомы с тем, как работают правила цитирования (как и когда заключать в кавычки, чтобы не допустить разделения слов), используйте его непосредственно в командной строке, как показано ниже.Это обеспечит сохранение переменных содержимого ONE и TWO, даже если они имеют пробелы.

./2.sh \
    --one "${ONE}" \
    ${TWO:+--two "${TWO}"} \
    --other

В качестве нескольких рекомендуемых рекомендаций

  • Всегда используйте строчные буквыимена переменных для пользовательских переменных, чтобы не путать их с переменными среды, поддерживаемыми самой оболочкой.
  • Использовать getopts() для более надежного анализа флагов аргументов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...