¿Por qué no puedo usar! (Patrón único) en zsh incluso después de encender kshglob?

8

Esto funciona en bash:

touch a b c
echo !(a)

Si ejecuto el script anterior en zsh (con kshglobon), se queja:

zsh: number expected

Si agrego |después a, funciona:

echo !(a|)

¿Por qué?

dedowsdi
fuente

Respuestas:

10

Porque en este caso, entra en conflicto con los calificadores glob simples ya que está al final del patrón. *(a1)se toma como los archivos accedidos por última vez en el último día. (a1)se trata como un calificador global. Entonces, en su !(a)caso, zsh se queja de la cantidad de días que faltan después del acalificador global (aquí se aplica al archivo llamado !).

En los zshglobos, la (...)agrupación se usa principalmente para la (foo|bar)alternancia, por lo que agregar una |es una forma documentada de asegurarse de que un final (...)no se trate como un calificador global.

Otra alternativa documentada es doblar el paréntesis ( !((a))) o podría agregar un calificador glob vacío (como !(a)(-)).

Para eliminar completamente esa ambigüedad, uno puede desactivar la bare_glob_qualopción ( set +o bareglobqual), después de lo cual los calificadores globales deben escribirse con la extendedglob (#q...)sintaxis ( *(#qa1)aquí).

La kshglobopción ( agregada en 1998 , aproximadamente al mismo tiempo que bashagregó que extglobaunque bash no tenía ningún glob extendido antes de eso) está principalmente disponible para el kshmodo de emulación ( emulate ksh), para zshpoder ejecutar kshscripts, donde kshglobestá habilitado y bareglobqualdeshabilitado. Cuando se introdujo por primera vez, después de habilitarlo kshglob, necesitaría especificar calificadores globales -(...)para evitar ese tipo de conflicto, pero eso causó demasiada confusión y entró en conflicto con la @-(...)sintaxis de ksh93, las opciones (#q...)y bareglobqualse introdujeron más tarde.

zshlos usuarios generalmente prefieren los propios set -o extendedgloboperadores glob ( ) extendidos de zsh que son más fáciles de escribir (para la mayoría) y más potentes (que los ksh88 habilitados con los que kshglobtambién se encuentran en bash -O extglob).

Por ejemplo, !(foo)se escribiría ^foo. El !(foo|)barembargo equivalente sería ya como (^(foo|))bar.

Otras traducciones ksh88 -> zsh:

  • *(x) -> x#
  • +(x) -> x##
  • @(x|y) -> x|y
  • ?(x) -> (x|)

Algunas traducciones ksh93 -> zsh:

  • ~(i:x)-> (#i)x(mayúsculas y minúsculas)
  • ~(N)x-> x(N)(nullglob, originado en zsh)
  • {1,5}(x) -> x(#c1,5)
  • @(foo&bar)-> foo~^baro^(^foo|^bar)

Algunos solo se encuentran en zsh:

  • <1-23> (rango de números decimales)
  • pattern~except
  • pattern(glob-qualifier) (la característica asesina de los globos zsh)
  • (pattern/)#(cualquier nivel de subdirectorios que coincida con pattern; la **/versión simplificada de (*/)#también se agregó a ksh93 y bash recientemente)
  • ***/* (globulación recursiva siguiendo enlaces simbólicos).
  • (#a1)foobar (coincidencia aproximada, permitiendo algunos errores, aquí 1)
  • ...
Stéphane Chazelas
fuente