Estou testando o Zsh, vindo do Bash. Eu estava tendo dificuldade para entender por que o Zsh reclama de um grep regex.
usr@rk1 ~ % tty | grep ^/dev/tty[1-7]$ > /dev/null 2>&1
zsh: no matches found: ^/dev/tty[1-7]$
Percebi que a saída desaparece e tudo fica bem se (1) eu colocar o regex entre aspas, (2) remover as barras do regex ou (3) usar setopt NO_NOMATCH
.
Do manual zshoptions:
NOMATCH (+3) <C> <Z>
Se um padrão para geração de nome de arquivo não tiver correspondências, imprima um erro, em vez de deixá-lo inalterado na lista de argumentos. Isso também se aplica à expansão de arquivo de um '~' ou '=' inicial.
Então, parece-me que o regex está sendo tratado como um padrão de nome de arquivo por causa das barras. Isso é considerado normal ou um bug?
Além disso, seria ótimo ter algo semelhante às páginas Bashism e BashPitfalls do GreyCat, mas para Zsh. Você conhece esse recurso?
Responder1
Se você definiu a EXTENDED_GLOB
opção, o padrão ^something
será usado para geração de nome de arquivo. Dezshexpnpágina de manual:
^x
(Requer que EXTENDED_GLOB seja definido.) Corresponde a qualquer coisa, exceto ao padrão x. Isso tem uma precedência maior que/
, portanto,^foo/bar
a pesquisa será feita em diretórios,.
exceto./foo
por um arquivo chamadobar
.
Então, ^/dev/tty[1-7]$
está tentando encontrar em cada subdiretório (nada é excluído, porque ^
é seguido diretamente por /
) do diretório atual para um arquivo chamado dev/tty1$
, dev/tty2$
, ..., dev/tty7$
que [1-7]
corresponda exatamente a um caractere no intervalo entre 1 e 7. $
é ' Não foi tratado de forma especial nesse caso.
Você já encontrou a solução, defina NO_NOMATCH
(pode ser perigoso, mas gosto muito porque tenho preguiça de digitar ;)
) ou coloque aspas (aspas simples ou duplas) o acento circunflexo.
Tente com print
o que está acontecendo:
$ 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]$
Sem EXTENDED_GLOB
set, o cursor é interpretado literalmente como um caractere normal. Portanto, citar é seu amigo novamente - desta vez apenas [1-7]
aciona a geração do nome do arquivo:
$ 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$
Então, resumindo: citar o padrão regex parece sempre uma boa ideia para mim - embora eu normalmente também tente salvar algumas teclas digitadas.