Расширение параметров Bash - PullRequest
2 голосов
/ 25 января 2011

У меня есть скрипт, который использует следующую логику:

if [ ! -z "$1" ]; then         # if any parameter is supplied
    ACTION=                    # clear $ACTION
else
    ACTION=echo                # otherwise, set it to 'echo'
fi

Это работает нормально, как есть.Однако, читая раздел Расширение параметров оболочки руководства bash, кажется, что это можно сделать за один шаг.Тем не менее, я не могу понять, как это сделать.

Я пробовал:

ACTION=${1:-echo}              # ends up with $1 in $ACTION

ACTION=${1:+}
ACTION=${ACTION:-echo}         # ends up always 'echo'

и несколько способов их вложения, но вложение, похоже, запрещенонасколько я могу судить.

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

Если это возможно, я хотел бы увидеть логику для выполнения этого кажущегося двухэтапного процесса, снет конструкции if / else, но с использованием только любой комбинации расширений параметров оболочки функций .

Спасибо.


EDIT для elderarthis:

Остальная часть сценария просто:

find . -name "*\?[NMSD]=[AD]" -exec ${ACTION} rm -f "{}" +

Я просто хочу ACTION=echo как проверку здравомыслия против себя, следовательно, передача любого аргумента будетна самом деле делаем удаление (обнуляя $ {ACTION}, тогда как передача аргументов без аргументов оставляет эхо там.

И я знаю TIMTOWTDI; я смотрю, чтобы увидеть, можно ли это сделать только с помощью вещи в командной консолиРаздел расширения параметров: -)


РЕДАКТИРОВАТЬ для Микеля:

$ cat honk.sh
#!/bin/bash
ACTION=${1-echo}
echo $ACTION
$ ./honk.sh
echo
$ ./honk.sh foo
foo

Последний должен иметь ACTION='' и, таким образом, возвращать пустую строку /нулевое значение.

Ответы [ 2 ]

6 голосов
/ 25 января 2011

Если я настаиваю на том, чтобы делать это менее чем в 4 строки и без вложенной оболочки, то я думаю, что я бы использовал:

ACTION=${1:+' '}
: ${ACTION:=echo}

Это немного обманывает - оно создает пустое действие, а не пустоедействие, если в сценарии есть аргумент.Если аргумента нет, то ACTION пуст перед второй строкой.Во второй строке, если действие пустое, установите для него значение «эхо».В расширении, поскольку вы (правильно) не заключаете в кавычки $ ACTION, для пробела не передается аргумент.

Тестер (xx.sh):

ACTION=${1:+' '}
: ${ACTION:=echo}

echo $ACTION rm -f a b c

Тесты:

$ sh xx.sh 1
rm -f a b c
$ sh xx.sh
echo rm -f a b c
$ sh xx.sh ''
echo rm -f a b c
$ 

Если последняя строка неверна, то удалите двоеточие перед плюсом.


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

ACTION=$([ -z "$1"     ] && echo echo)
ACTION=$([ -z "${1+X}" ] && echo echo)

Первая соответствует первой версии, показанной выше (пустые первые аргументы рассматриваются как отсутствующие);вторая имеет дело с пустыми аргументами как присутствующими.Вы можете написать:

ACTION=$([ -z "${1:+X}" ] && echo echo)

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


С момента уценкипримечание в моем комментарии запутало систему (или я ошибся, но не смог исправить это достаточно быстро), мой последний комментарий (с некоторыми изменениями) должен выглядеть следующим образом:

Запись ${var:+' '} означает «если $var установлено и не пусто, затем используйте то, что следует за + '(которое в данном случае является единственным пробелом).Обозначение ${var+' '} означает «если установлено $var - независимо от того, пусто оно или нет - тогда используйте то, что следует за +».Эти другие расширения аналогичны:

  • ${var:=X} - установите $var в X, если оно уже не имеет непустого значения.
  • ${var:-X} - расширяется до $var если оно имеет непустое значение и расширяется до X, если $var не установлено или пусто

Удаление двоеточия удаляет «пустую» часть теста.

2 голосов
/ 25 января 2011
ACTION=${1:-echo}

является правильным.

Убедитесь, что он находится в верхней части вашего скрипта, прежде чем что-либо изменит $1 (например, перед любой командой set).Кроме того, это не будет работать внутри функции, потому что $1 будет первым параметром функции.

Также проверьте, установлено ли $1, но ноль, в этом случае исправьте, как вы вызываетеили используйте ACTION=${1-echo} (обратите внимание, что нет :).


Обновление

Ах, я предположил, что вы имели в виду обратное,потому что в действительности это не имело смысла.

Это все еще кажется странным, но я думаю, что в качестве умственного упражнения вам может понадобиться что-то вроде этого:

#!/bin/bash
shopt -s extglob
ACTION=$1
ACTION=${ACTION:-echo}
ACTION=${ACTION/!(echo)/}    # or maybe ACTION=${ACTION#!(echo)}
echo ACTION=$ACTION

Это не совсем правильно:это дает ACTION=o, но я думаю, что что-то в этом роде должно работать.

Далее, если вы передадите echo как $1, это останется эхом, но я не думаю, что это плоховещь.

Это также ужасно уродливо, но вы знали об этом, когда задавали вопрос.: -)

...