¿Cuál es la diferencia entre a[bc]d
y a{b,c}d
? ¿Por qué la gente usa a{b,c}d
cuando ya existe a[bc]d
?
brace-expansion
pattern-matching
Weijun Zhou
fuente
fuente
command a[bc]d
?ls
y solo prueba caracteres únicos, parecería que funcionan igual.Respuestas:
Los dos son bastante diferentes.
a[bc]d
es un patrón de nombre de archivo (en shells que no seanfish
). Se expandirá a los dos nombres de archivoabd
y,acd
si son nombres de archivos existentes en el directorio actual.La
[...]
parte es una expresión entre corchetes que coincide con un solo carácter de los enumerados (o elementos de clasificación cuando se incluyen rangos). Para que coincida con el patróna[bc]d
, el carácter entre las cadenasa
yd
en un nombre de archivo debe ser ab
o ac
.Si
abd
existe, peroacd
no existe, entonces solo se expandiríaabd
y viceversa.Si ninguno
abd
, niacd
existir, dependiendo de la cáscara y las opciones, que daría lugar a un error (Unix originalsh
,(t)csh
,zsh
,fish
,bash -O failglob
) y posiblemente salir de la cáscara, o salir de la unexpanded¹ patrón (Bourne-como yrc
-como conchas) o ampliar a nada (bash/zsh/yash -o nullglob
algunas versiones anteriores defish
Unix originalsh
y(t)csh
si hay otros globos coincidentes en el mismo comando).a{b,c}d
es una expansión de llaves (en conchas que las admiten). Se expandirá a las dos cadenasabd
yacd
.La
{...}
parte es un conjunto delimitado por comas de cadenas (en este ejemplo, en algunos cáscara, también puede ser un intervalo tal comoa..k
o20..25
o más avanzadas que son como00..20..2
o0..20..2%02d
), y la expansión se calcula mediante la combinación de cada una de estas cadenas con el flanqueo cuerdasa
yd
. Estas cadenas podrían ser más largas que un solo personaje y también podrían ser expansiones de llaves.La expansión ocurre independientemente de si estas cadenas corresponden a nombres de archivos existentes o no.
Si está construyendo cadenas, use una expansión de llaves. Si está haciendo coincidir nombres de archivo, use un patrón de nombre de archivo.
¹ En este caso particular,
a[bc]d
podría ser el nombre de un archivo existente, por lo que es potencialmente peligroso usar cosas comorm -f ./*.[ch]
en esos shells yrm -f ./*.{c,h}
es un problema menor.fuente
a{b,c}d
, las partesb
yc
no necesitan ser letras individuales; por ejex{ten,ci}sion
. Mientrasex[tenci]sion
o lo que sea solo coincidirá con una de estas letras.a[bc]d
es coincidencia de patrones y es parte del estándar POSIX. En POSIX, esto se introduce como la "expresión de paréntesis de patrón". Está documentado en la sección 2.13 del manual.La Sección 2.13.3 también menciona algo que se comporta de manera diferente de lo que uno esperaría para las expresiones regulares habituales cuando se usa para la expansión de nombre de archivo (énfasis por mí)
a{b,c}d
es una expansión de llaves , no está en la especificación de POSIX. Aquí está la parte correspondiente del manual de bash (énfasis por mí):Según el comentario de @mosvy, esto apareció por primera vez,
csh
pero el comportamientobash
es diferentecsh
y de otros shells. Este tipo de expansión de llaves también está presente englob(3)
.Hay otro tipo de expansión de llaves
{a..z}
que solo apareció después debash
3.0, y hay más agregadas enbash
4.0.En un shell donde está activado el globbing, ejecutar en una carpeta vacía, se devuelve el siguiente resultado
En respuesta al comentario de @ Jesse_b, si estás en un shell interactivo y ambos aplican,
a[bc]d
es menos difícil escribir. Por ejemplogrep pattern [ab][12].txt
.fuente
csh
, mucho antesbash
. También está presente en la función de biblioteca glob (3). La diferencia es quebash
se realiza antes de otras expansiones:a=A; ab=A/B; ac=A/C; echo $a{b,c}
funcionará en bash de manera diferente a cualquier otro shell.