¿Por qué se echo {1,2,3}expande a 1 2 3, que es un comportamiento esperado, mientras que echo [[:digit:]]regresa [[:digit:]]mientras esperaba que imprimiera todos los dígitos de 0a 9?
Porque son dos cosas diferentes. El {1,2,3}es un ejemplo de expansión de llaves . El armazón{1,2,3} expande la construcción , incluso antes de verla. Puede ver qué sucede si usa :echoset -x
$ set-x
$ echo {1,2,3}+ echo 123123
Como puede ver, el comando echo {1,2,3}se expande para:
echo 123
Sin embargo, [[:digit:]]es una clase de caracteres POSIX . Cuando se lo da echo, el shell también lo procesa primero, pero esta vez se está procesando como un globo de shell . funciona de la misma manera que si ejecuta, echo *que imprimirá todos los archivos en el directorio actual. Pero [[:digit:]]es un globo de shell que coincidirá con cualquier dígito. Ahora, en bash, si un globo de shell no coincide con nada, se expandirá a sí mismo:
En ambos casos, echosolo imprime lo que el shell le dice que imprima, pero en el segundo caso, ya que el globo coincide con algo ( /etc) se le dice que imprima ese algo.
Entonces, dado que no tiene ningún archivo o directorio cuyo nombre consista exactamente en un dígito (que es lo [[:digit:]]que coincidiría), el globo se expande a sí mismo y obtiene:
$ echo [[:digit:]][[:digit:]]
Ahora, intente crear un archivo llamado 5y ejecute el mismo comando:
$ echo [[:digit:]]5
Y si hay más de un archivo coincidente:
$ touch 15
$ echo [[:digit:]]15
Esto está (más o menos) documentado en man bashla explicación de las nullglobopciones que desactiva este comportamiento:
nullglobIfset, bash allows patterns which match no files (seePathnameExpansion above) to expand to a null string,
rather than themselves.
Consulte también shopt -s failglobpara obtener un comportamiento más útil similar al de los proyectiles modernos como zsho fish.
Stéphane Chazelas
Estoy de acuerdo con Stéphane, uso failglob. nullglobpuede causar problemas inesperados, por ejemplo, al pegar una URL que tiene un ?.
Kevin
1
Claro, solo mencioné nullglobpara demostrar que el patrón está siendo interpretado como un globo por el caparazón.
terdon
14
{1,2,3}es una expansión de llaves , se expande a las palabras enumeradas sin tener en cuenta su significado.
[...]es un grupo de caracteres, utilizado en la expansión de nombre de archivo (o comodín, o glob) de manera similar al asterisco *y al signo de interrogación ?. Coincide con cualquier carácter individual incluido en la lista, o con caracteres que son miembros de grupos con nombre, como [:digit:]si se enumeran. El comportamiento predeterminado de la mayoría de los shells es dejar el comodín como está si no hay archivos que lo coincidan.
(Tenga en cuenta que realmente no puede convertir un comodín / patrón en el conjunto de cadenas que coincidiría. El asterisco puede coincidir con cualquier cadena de cualquier longitud, por lo que expandir cualquier patrón que lo contenga produciría una lista infinita de cadenas).
Entonces:
$ bash -c 'echo [[:digit:]]'# bash leaves it as-is[[:digit:]]
$ zsh -c 'echo [[:digit:]]'# zsh by default complains if no match
zsh:1: no matches found:[[:digit:]]
$ touch 13 d i g t
$ bash -c 'echo [[:digit:]]'# now there are two matches13# note that d, i, g and t do NOT match
Pero aún:
$ bash -c 'echo {1,2,3}'123
Ambos están expandidos por el shell , no importa si el comando que está ejecutando es ls, o echoo rm. También tenga en cuenta que si se cita cualquiera de esos, no se expandirán:
$ bash -c 'echo "[[:digit:]]"'# even though matching files still exist[[:digit:]]
$ bash -c 'echo "{1,2,3}"'{1,2,3}
gracias por su respuesta, soy nuevo en Linux, así que déjenme preguntarles cómo se relaciona echo con los archivos 1 3, su función es imprimir sus argumentos para que stdout no
busque
1
@AbdAllahTalaat esto no tiene nada que ver con echo, en realidad. El shell (por ejemplo, bash) se "expandirá" [[:digit:]]antes de pasarlo echo, por lo que echonunca ve [[:digit:]], solo ve 1 3. Puede ver esto en acción ejecutando set -xlo que imprimirá los comandos reales que se están ejecutando (ejecute set +xpara apagarlo nuevamente).
terdon
@AbdAllahTalaat, echono busca archivos, el shell sí, antes de ejecutar el echo.
ilkkachu
Especialmente porque creo que en DOS / Windows las utilidades expanden los comodines, no el shell. (
Tal
lo siento chicos, cambié la respuesta correcta a la respuesta de tedron porque su comentario contenía el significado de que bash es lo que el trabajo no hace eco ... su respuesta también contenía ese significado ... todos ustedes me ayudaron ... deseé poder poner respuesta correcta para todas sus respuestas y comentarios
AbdAllah Talaat
4
{1,2,3}(y, por ejemplo, {1..3}son expansiones de llaves . El shell las interpreta antes de la ejecución del comando.
[[:digit:]]es un token de coincidencia de patrones , pero no lo está utilizando en una ubicación con ningún archivo que coincida con ese patrón. Si usa una coincidencia de patrón que no tiene coincidencias, se expande a sí misma:
Respuestas:
Porque son dos cosas diferentes. El
{1,2,3}
es un ejemplo de expansión de llaves . El armazón{1,2,3}
expande la construcción , incluso antes de verla. Puede ver qué sucede si usa :echo
set -x
Como puede ver, el comando
echo {1,2,3}
se expande para:Sin embargo,
[[:digit:]]
es una clase de caracteres POSIX . Cuando se lo daecho
, el shell también lo procesa primero, pero esta vez se está procesando como un globo de shell . funciona de la misma manera que si ejecuta,echo *
que imprimirá todos los archivos en el directorio actual. Pero[[:digit:]]
es un globo de shell que coincidirá con cualquier dígito. Ahora, en bash, si un globo de shell no coincide con nada, se expandirá a sí mismo:Si el globo coincide con algo, se imprimirá:
En ambos casos,
echo
solo imprime lo que el shell le dice que imprima, pero en el segundo caso, ya que el globo coincide con algo (/etc
) se le dice que imprima ese algo.Entonces, dado que no tiene ningún archivo o directorio cuyo nombre consista exactamente en un dígito (que es lo
[[:digit:]]
que coincidiría), el globo se expande a sí mismo y obtiene:Ahora, intente crear un archivo llamado
5
y ejecute el mismo comando:Y si hay más de un archivo coincidente:
Esto está (más o menos) documentado en
man bash
la explicación de lasnullglob
opciones que desactiva este comportamiento:Si configura esta opción:
fuente
shopt -s failglob
para obtener un comportamiento más útil similar al de los proyectiles modernos comozsh
ofish
.failglob
.nullglob
puede causar problemas inesperados, por ejemplo, al pegar una URL que tiene un?
.nullglob
para demostrar que el patrón está siendo interpretado como un globo por el caparazón.{1,2,3}
es una expansión de llaves , se expande a las palabras enumeradas sin tener en cuenta su significado.[...]
es un grupo de caracteres, utilizado en la expansión de nombre de archivo (o comodín, o glob) de manera similar al asterisco*
y al signo de interrogación?
. Coincide con cualquier carácter individual incluido en la lista, o con caracteres que son miembros de grupos con nombre, como[:digit:]
si se enumeran. El comportamiento predeterminado de la mayoría de los shells es dejar el comodín como está si no hay archivos que lo coincidan.(Tenga en cuenta que realmente no puede convertir un comodín / patrón en el conjunto de cadenas que coincidiría. El asterisco puede coincidir con cualquier cadena de cualquier longitud, por lo que expandir cualquier patrón que lo contenga produciría una lista infinita de cadenas).
Entonces:
Pero aún:
Ambos están expandidos por el shell , no importa si el comando que está ejecutando es
ls
, oecho
orm
. También tenga en cuenta que si se cita cualquiera de esos, no se expandirán:fuente
[[:digit:]]
antes de pasarloecho
, por lo queecho
nunca ve[[:digit:]]
, solo ve1 3
. Puede ver esto en acción ejecutandoset -x
lo que imprimirá los comandos reales que se están ejecutando (ejecuteset +x
para apagarlo nuevamente).echo
no busca archivos, el shell sí, antes de ejecutar elecho
.{1,2,3}
(y, por ejemplo,{1..3}
son expansiones de llaves . El shell las interpreta antes de la ejecución del comando.[[:digit:]]
es un token de coincidencia de patrones , pero no lo está utilizando en una ubicación con ningún archivo que coincida con ese patrón. Si usa una coincidencia de patrón que no tiene coincidencias, se expande a sí misma:fuente