Zsh обрабатывает строку как шаблон имени файла и выдает сообщение об этом (опция NOMATCH)

Zsh обрабатывает строку как шаблон имени файла и выдает сообщение об этом (опция NOMATCH)

Я пробую Zsh, перейдя с Bash. У меня возникли некоторые трудности с пониманием того, почему Zsh жалуется на grep regex.

usr@rk1 ~ % tty | grep ^/dev/tty[1-7]$ > /dev/null 2>&1
zsh: no matches found: ^/dev/tty[1-7]$

Я заметил, что вывод исчезает, и все становится хорошо, если (1) я заключаю регулярное выражение в кавычки, (2) удаляю косые черты из регулярного выражения или (3) использую setopt NO_NOMATCH.

Из руководства zshoptions:

НЕСОВПАДЕНИЕ (+3) <C> <Z>

Если шаблон для генерации имени файла не имеет совпадений, вывести ошибку, а не оставлять его без изменений в списке аргументов. Это также относится к расширению файла начального '~' или '='.

Итак, мне кажется, что регулярное выражение рассматривается как шаблон имени файла из-за слешей. Это считается нормой или ошибкой?

Также было бы здорово иметь что-то похожее на страницы GreyCat's Bashism и BashPitfalls, но для Zsh. Знаете ли вы такой ресурс?

решение1

Если вы установили эту EXTENDED_GLOBопцию, шаблон ^somethingбудет использоваться для генерации имени файла.zshexpnСтраница руководства:

^x (Требуется установка EXTENDED_GLOB.) Соответствует всему, кроме шаблона x. Имеет более высокий приоритет, чем /, поэтому ^foo/barбудет искать каталоги, за .исключением ./fooфайла с именем bar.

Итак, ^/dev/tty[1-7]$пытается найти в каждом подкаталоге (ничего не исключается, поскольку ^за ним непосредственно следует /) текущего каталога файл с именем dev/tty1$, dev/tty2$, ..., dev/tty7$который [1-7]соответствует ровно одному символу в диапазоне от 1 до 7. $в этом случае не рассматривается как нечто особенное.

Решение вы уже нашли, установите NO_NOMATCH(может быть, это опасно, но мне это очень нравится, так как я ленивый в наборе текста ;)) или заключите в кавычки (одинарные или двойные) курсор.

Попробуйте printто, что происходит:

$ setopt nomatch extended_glob
$ echo ^/dev/tty[1-7]$
zsh: no matches found: ^/dev/tty[1-7]$

# ^ is doing filename generation in every sub-dir
$ touch foo/dev/tty5$
$ echo ^/dev/tty[1-7]$
foo/dev/tty5$

# quote to prevent filename generation
$ echo "^/dev/tty[1-7]$"
^/dev/tty[1-7]$
$ echo '^/dev/tty[1-7]$'
^/dev/tty[1-7]$

Без EXTENDED_GLOBустановки каретка интерпретируется буквально как обычный символ. Так что кавычки снова ваш друг — на этот раз только запускает [1-7]генерацию имени файла:

$ setopt nomatch no_extended_glob
$ echo ^/dev/tty[1-7]$
zsh: no matches found: ^/dev/tty[1-7]$

# quote to prevent filename generation
$ echo ^/dev/tty"[1-7]"$
^/dev/tty[1-7]$

# caret is interpreted literally
$ mkdir ^/dev -p
$ touch ^/dev/tty5$
$ echo ^/dev/tty[1-7]$
^/dev/tty5$

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

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