Me gustaría saber si una cadena $stringcoincidiría con un patrón global $pattern. $stringpuede 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 $stringsería igualado por $pattern1, $pattern2o cualquier otro patrón global arbitraria. Esto es lo que he intentado hasta ahora:
[[ "$string" = $pattern ]]Esto casi funciona, excepto que
$patternse interpreta como un patrón de cadena y no como un patrón global.[ "$string" = $pattern ]El problema con este enfoque es que
$patternse expande y luego se realiza una comparación de cadenas entre$stringy la expansión de$pattern.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]Este funciona, pero solo si
$stringcontiene un archivo que existe.[[ $string =~ $pattern ]]Esto no funciona porque el
=~operador hace$patternque 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,barybaz.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.$stringes la expansión de parámetros. Todo esto se hace en diferentes momentos y por diferentes mecanismos.caseglobal , 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 -fdeshabilita 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$stringcoincide$patternpuedes 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
sedoperación simple .Usaría grep así:
Lo que da la salida:
fuente
en zsh:
fuente