Tengo 3 directorios en la ruta actual.
$ls
a_0db_data a_clean_0db_data a_clean_data
$ls a_*_data
a_0db_data:
a_clean_0db_data:
a_clean_data:
$ls a_[a-z]*_data
a_clean_0db_data:
a_clean_data:
Esperaba que el último comando ls coincidiera solo a_clean_data
. ¿Por qué también coincidió con el que contiene 0
?
bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)
bash
regular-expression
wildcards
usuario13107
fuente
fuente
a_*_data
coincida con alguno de estos archivos no te sorprendió?Respuestas:
La
[a-z]
parte no es lo que coincide con el número; es el*
. Puede ser confuso el shell globbing y las expresiones regulares .Herramientas como
grep
aceptar varios tipos de expresiones regulares ( básico de forma predeterminada,-E
para extendido,-P
para expresiones regulares de Perl )Por ejemplo (
-v
invierte el partido)Si desea utilizar una expresión regular de bash, aquí hay un ejemplo sobre cómo probar si la variable
$ref
es un número entero:fuente
Entonces el problema es: ¿por qué
a_[a-z]*_data
coincidea_clean_0db_data
?Esto se puede dividir en cuatro partes:
a_
coincide con el comienzo dea_clean_0db_data
, dejandoclean_0db_data
que coincida[a-z]
coincide con cualquier personaje en el rangoa-z
(por ejemploc
), dejandolean_0db_data
que coincida*
coincide con cualquier número de caracteres, p. ej.lean_0db
_data
coincide con el final_data
En las expresiones regulares,
[a-z]*
significaría cualquier número de caracteres (incluido cero) en el rango de a..z , pero se trata de un bloqueo de shell, no de expresiones regulares.Si desea expresiones regulares, algunas
find
implementaciones tienen un-regex
predicado para eso:El
-maxdepth
es aquí sólo para limitar los resultados de búsqueda-a la carpeta que se encuentra. La expresión regular coincide con la totalidad de nombre de archivo, por lo tanto, he añadido una^.*/
para que coincida con la parte de rutafuente
*
en los patrones de shell coincide con 0 o más caracteres. No debe confundirse con el*
operador de expresión regular que significa 0 o más del átomo anterior .No hay equivalente de regexp
*
en los patrones básicos de shell. Sin embargo, varios shells tienen extensiones para eso.ksh
tiene*(something)
:puede tener lo mismo
bash
conshopt -s extglob
ozsh
consetopt kshglob
:En
zsh
conextendedglob
habilitado,#
es equivalente a regexp*
:En versiones recientes de
ksh93
, también puede usar expresiones regulares en globos. Aquí con expresiones regulares extendidas :Tenga en cuenta que
[a-z]
coincide con diferentes cosas según la configuración regional actual. Por lo general coincide con sólo las 26a
az
las letras latinas no acentuados en laC
configuración regional. En otros entornos locales, generalmente coincide más y no siempre tiene sentido. Para que coincida con una letra en su localidad, puede preferir[[:alpha:]]
.fuente
[a-z]
coincidencia más que las 26 letras coincidentes en la configuración regional C? Lo que recuerdo de la última vez que vi esto, todas las codificaciones prácticamente utilizadas en las variantes de Unix tenían ISO-646 como base (luego los 128 códigos superiores se usaron de manera diferente, directamente para caracteres en codificaciones como el ISO-8859-X, combinados en codificaciones como UTF-8 o la familia EUC). Incluso AIX no tenía configuraciones regionales EBCDIC (al menos como estaba disponible para mí). Recuerdo haber intentado averiguar si los estándares POSIX / UNIX lo exigían, pero no recuerdo el resultado.[a-z]
generalmente incluyeé
oí
(pero no necesariamenteź
) en los entornos locales donde el conjunto de caracteres los tiene, ya sea que el punto de código en esa codificación esté entre el de a y z o no. Solo la configuración regional C garantiza un orden de clasificación basado en el valor del punto de código. Vea esta otra respuesta para más detalles.