Expressão curinga ZSH que limita o suporte à repetição?

4

Alguém sabe se existe uma maneira de incorporar restrições de repetição em expressões curinga do ZSH?

Por exemplo, para combinar todos os arquivos que começam com "ABC" seguindo por um ou mais números, o grep one poderia ser feito:

ls | grep -e "ABC[0-9]\+"

Existe alguma maneira de fazer isso diretamente com seqüências de glob do ZSH? Algo ao longo das linhas de:

ls "ABC[0-9]\+"

Analisei os documentos do ZSH e pesquisei por algo assim, mas até agora não encontrei tal apoio.

Alguém sabe se isso é possível?

    
por Keith Hughitt 23.11.2016 / 14:59

3 respostas

4

Sim, use ## para corresponder a uma ou mais ocorrências de [0-9] como:

ABC[0-9]##

Isso requer que extendedglob seja definido, o que é por padrão. Se não definido, defina-o primeiro:

setopt extendedglob

Exemplo:

% print -l ABC*
ABC
ABC75475
ABC8
ABC90

% print -l ABC[0-9]##
ABC75475
ABC8
ABC90
    
por 23.11.2016 / 15:05
2

Com extendedglob ativado:

$ setopt extendedglob
$ print -rl -- perl[[:digit:]]##
perl5

ou com kshglob ativado e bareglobqual desativado:

$ setopt kshglob
$ unsetopt bareglobqual
$ print -rl -- perl+([[:digit:]])
perl5

Observe que usar [:digit:] para corresponder a todos os dígitos considerados na localidade atual. Se você quiser corresponder apenas 0 a 9 , defina LC_ALL=C ou use literalmente [0123456789] .

Você pode especificar o número da correspondência, como a expressão regular {n,m} usando o sinalizador (#cN,M) globbing em qualquer lugar em que os operadores # e ## possam ser usados, exceto em (*/)# e (*/)## :

$ print -rl -- perl[[:digit:]](#c1)
perl5
$ print -rl -- perl[[:digit:]](#c2)
zsh: no matches found: perl[[:digit:]](#c2)
    
por 23.11.2016 / 15:13
1

Desça até “ Generation de nome de arquivo ” e ative extended_glob (que deve ser o padrão, mas não é para compatibilidade com versões anteriores) ou ksh_glob . Os globs estendidos e os ksh's de zsh têm o poder total das expressões regulares.

ERE syntax      ksh glob      zsh extended glob
(foo)*          *(foo)        (foo)#
(foo)+          +(foo)        (foo)##
(foo)?          ?(foo)        (|foo)
(foo|bar)       @(foo|bar)    (foo|bar)

Lembre-se de que a maioria das ferramentas que usam expressões regulares as usam como padrões pesquisa que devem corresponder a uma substring, mas globs sempre são usados como padrões que devem corresponder à string inteira. Por exemplo, foofoobar não corresponde ao zsh glob (foo)## , já que depois de foofoo sobrou algum texto.

O Zsh possui operadores adicionais que não ampliam o poder expressivo, mas tornam algumas expressões mais fáceis de serem escritas. Os operadores ^ e ~ ( extended_glob ) e !(…) ( ksh_glob ) fornecem negação, e. ^foo ou !(foo) corresponde a qualquer coisa, exceto foo , que na sintaxe de regex requer o |[^f].*|f[^o].*|fo[^o].* pesado. O operador <…-…> (específico de zsh, não requer extended_glob ) corresponde a qualquer número inteiro (em notação decimal) em um intervalo, por exemplo, <3-11> corresponde 3 e 10 mas não 30 ou 1 .

Portanto, excluindo problemas como caracteres não imprimíveis, ls | grep -e "ABC[0-9]\+" pode ser escrito de maneiras como

print -lr -- *ABC[0-9]##*(N)      # requires extended_glob
print -lr -- *ABC+([0-9])*(N)      # requires ksh_glob
print -lr -- *ABC+<->(N)

Mas como “um ou mais dígitos e qualquer coisa” é equivalente a “um dígito e qualquer coisa”, também pode ser escrito

print -lr -- *ABC[0-9]*(N)
    
por 24.11.2016 / 01:48