Я пробую 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$
Итак, подводя итог: заключение шаблона регулярного выражения в кавычки всегда кажется мне хорошей идеей, хотя я обычно также стараюсь сэкономить несколько нажатий клавиш.