Me gustaría saber si una cadena $string
coincidiría con un patrón global $pattern
. $string
puede o no ser el nombre de un archivo existente. ¿Cómo puedo hacer esto?
Asumir los siguientes formatos para mis cadenas de entrada:
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
Me gustaría encontrar un lenguaje bash que determina si $string
sería igualado por $pattern1
, $pattern2
o cualquier otro patrón global arbitraria. Esto es lo que he intentado hasta ahora:
[[ "$string" = $pattern ]]
Esto casi funciona, excepto que
$pattern
se interpreta como un patrón de cadena y no como un patrón global.[ "$string" = $pattern ]
El problema con este enfoque es que
$pattern
se expande y luego se realiza una comparación de cadenas entre$string
y la expansión de$pattern
.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
Este funciona, pero solo si
$string
contiene un archivo que existe.[[ $string =~ $pattern ]]
Esto no funciona porque el
=~
operador hace$pattern
que se interprete como una expresión regular extendida, no como un patrón global o comodín.
{bar,baz}
no es un patrón. Es la expansión de parámetros. La diferencia sutil pero crítica{bar,baz}
se expande muy pronto en múltiples argumentos,bar
ybaz
.ls /foo/*
ahora puedes igualar en unfoo/{bar,baz}
realidad es una expansión de llaves (no una expansión de parámetros) mientras quefoo/*
es una expansión de nombre de ruta.$string
es la expansión de parámetros. Todo esto se hace en diferentes momentos y por diferentes mecanismos.case
global , la instrucción realiza la Expansión del nombre de ruta ("globalización") según el manual de Bash.Respuestas:
No hay una solución general para este problema. La razón es que, en bash, la expansión de llaves (es decir,
{pattern1,pattern2,...}
y la expansión de nombre de archivo (también conocidos como patrones globales) se consideran cosas separadas y se expanden bajo diferentes condiciones y en diferentes momentos. Aquí está la lista completa de expansiones que realiza bash:Dado que solo nos preocupamos por un subconjunto de estos (quizás expansión de llaves, tilde y nombre de ruta), es posible usar ciertos patrones y mecanismos para restringir la expansión de manera controlable. Por ejemplo:
La ejecución de este script genera el siguiente resultado:
Esto funciona porque
set -f
deshabilita la expansión del nombre de ruta, por lo que solo la expansión de llaves y la expansión de tilde ocurren en la declaraciónfor pattern in /foo/{*,foo*,bar*,**,**/*}
. Luego podemos usar la operación[[ $string == $pattern ]]
de prueba para probar contra la expansión del nombre de ruta después de que la expansión de la llave ya se haya realizado.fuente
No creo que
{bar,baz}
sea un patrón glob de concha (aunque ciertamente lo/foo/ba[rz]
es), pero si quieres saber si$string
coincide$pattern
puedes hacerlo:Puedes hacer tantas como quieras:
fuente
{bar,baz}
no es un patrón global. Ya he encontrado una solución a mi pregunta que tiene esto en cuenta.Como Patrick señaló que necesita un "tipo diferente" de patrón:
Las cotizaciones no son necesarias allí.
fuente
sed
operación simple .Usaría grep así:
Lo que da la salida:
fuente
en zsh:
fuente