Используя ИЛИ шаблоны в подстановочных знаках оболочки

Соответствующий раздел руководства удара перечисляет 5 различных конструкций, которые могут использоваться для условной оценки. Из них, if, case, и [[ .. ]] конструкции, вероятно, обычно используются в реальном коде, хотя (( .. )) конструкция будет часто привыкать в сценариях, которые делают сложный подсчет или другие числовые операции.

Но они не упоминают другую очень стандартную форму, используемую для ветвления в ударе, который должен просто выполнить команду в сочетании с оценкой короткого замыкания, например

grep -q needle haystack.txt && echo "Needle located!" || echo "No dice or needles.";

&& и || логические операторы: "и" и "или" соответственно.

Это - эффективно то же как

if grep -q needle haystack.txt; then echo "yea"; else echo "nay"; fi;

но работы по-другому: в первой форме условная логика действительно появляется как побочный эффект фактической явной цели кода, который должен, по крайней мере якобы, оценить логические операторы. Этот вид конструкции также обычно замечается в C и коде JavaScript.

Это работает путем поиска легких путей: части выражения, например. x && y || z, оценены слева направо. Если левая сторона логического и, например, x в x && y, оценивает ко лжи, bash не потрудился оценивать y часть, потому что в той точке это уже знает это x && y ложь.

Обратное верно для логического ors: true || z всегда оценивает к истинному, независимо от того, чем оказывается z.

Таким образом, если grep выходит ложь, bash может пропустить это сначала echo, потому что та часть выражения не может возможно быть верной. Таким образом, это идет дальше к второму echo. С другой стороны, если grep является верным, первым echo выполняется (приводящий к тем, ну, в общем, отражаемым словам..). В этой точке bash сделан, потому что безотносительно значения правой стороны ||, результат выражения все еще будет верен.

Для получения ощущения пути работы удара с условными выражениями, лучше делать некоторое экспериментирование на командной строке. Команда

echo $?;

повторит код возврата предыдущего оператора. Это - код ошибки, таким образом, 0 верное средство, и ненулевое значение означает ложь. Это немного сбивает с толку сначала, но Вы привыкаете к нему.

Таким образом, можно сделать, например

$ (( 1 + 2 == 3 )); echo $?
0
$ (( 1 + 2 == 4 )); echo $?
1

и выполните подобные тесты с [[ .. ]] создайте для получения ощущения этих основных стандартных блоков. После того как Вам сделали это, движение к if и затем case операторы.

Что касается ответа на Ваш вопрос, ну, в общем, я думаю, что это очень зависит от контекста, в котором его спросили. Но получение хорошего понимания различных вариантов должно помочь Вам выяснить то, что они ищут там.

55
09.10.2012, 02:11
3 ответа

Вам даже не нужен расширенный globbing, позволенный сделать то, что Вы хотите. Это будет работать в ударе:

ls {day*,night*}
69
27.01.2020, 19:33
  • 1
    No это не делает: touch day.txt; touch night.txt; ls {*day,night*} результаты в ls: *day: No such file or directory –  Matteo 08.10.2012, 19:46
  • 2
    я адаптировал текст исходного плаката; я думал, что это было ясно. вздох. Текст обновляется. Конечно, Вы видите, что механизм работает? –  itsbruce 08.10.2012, 19:50
  • 3
    Или возможно *{day,night}* ближе к тому, что хочет OP. –  derobert 08.10.2012, 20:24

Нет никакой опции в ls для фильтрации на имени файла, но в большинстве оболочек существует globbing расширение man bash /Pattern Matching

ksh

ls -lrtd -- *@(day|night)*

zsh

setopt extendedglob
ls -lrtd -- *(day|night)*

или:

setopt kshglob
ls -lrtd -- *@(day|night)*

удар

shopt -s extglob
ls -lrtd -- *@(day|night)*

В любой из этих трех оболочек можно сделать это, но отметить что, если один из случаев не соответствует никакому файлу, что шаблон оставят нерасширенным (например. *day* night1.txt othernight.txt если нет никакого имени файла, содержащего day; посмотрите man bash /EXPANSION или /Brace Expansion конкретно):

ls -lrtd -- *{day,night}*

В любых оболочках можно сделать:

ls -lrtd -- *day* *night*

В zsh, если существует любой нет day или night файл, последние две команды перестанут работать; установите nonomatch или csh_null_glob опция, или добавляют (N) после каждого шаблона для предотвращения этого.

25
27.01.2020, 19:33
  • 1
    Что относительно *{day,night}*. Я отредактировал бы его, но я не знаю, какие оболочки поддерживают его? –  Random832 08.10.2012, 18:12
  • 2
    @Random832 в bash, ksh, и zsh (ни одному не нужен расширенный globbing), но нет sh - однако, Nahuel, последний "все оболочки" пример, действительно работает в sh. –  Izkata 08.10.2012, 21:04

Оболочки не делают регулярных выражений использования для расширения аргумента.

Можно включить расширенное сопоставление с образцом

$ shopt -s extglob

и затем

$ ls @(day|night).txt
day.txt   night.txt

См., например, Справочник Bash (Сопоставление с образцом)

14
27.01.2020, 19:33

Теги

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