Sensibilidad a mayúsculas y minúsculas en globbing de corchetes

10

Normalmente, el golpeteo de bash distingue entre mayúsculas y minúsculas:

$ echo c*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo C*
CarePackage.md ChocRippleCake.md Clips

El uso de corchetes no parece cambiar esto:

$ echo [c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C]*
CarePackage.md ChocRippleCake.md Clips

Todavía no lo cambia si se usa un guión:

$ echo [c-c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C-C]*
CarePackage.md ChocRippleCake.md Clips

Pero las letras están intercaladas:

$ echo [B-C]*
CarePackage.md casefix.pike cdless chalices.py charconv.py chocolate.pike ChocRippleCake.md circum.py clip.pike Clips cpustats.pike crop.pike cwk2txt.py
$ echo [b-c]*
beehive-anthem.txt bluray2mkv.pike branch branchcleanup.pike burdayim.pike casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py

Esto sugiere que el guión está usando un orden local, "AaBbCcDd". Entonces: ¿hay alguna forma de glob para todos los archivos que comienzan con una letra mayúscula?

rosuav
fuente
3
¡También tenga en cuenta el error de que [AZ] coincide con todas las letras minúsculas excepto 'z'!
PJTraill

Respuestas:

12

En bash versión 4.3 y posterior, hay una opción de shopt llamada globasciiranges:

Según las páginas de manual de Shopt Builtin GNU :

globasciiranges
Si se establece, las expresiones de rango utilizadas en las expresiones de corchetes de coincidencia de patrones (ver Coincidencia de patrones) se comportan como si estuvieran en el entorno local tradicional de C al realizar comparaciones. Es decir, la secuencia de clasificación del entorno local actual no se tiene en cuenta, por lo que 'b' no se clasificará entre 'A' y 'B', y los caracteres ASCII en mayúsculas y minúsculas se agruparán.

Como resultado puedes

$ shopt -s globasciiranges 
$ echo [A-Z]*

Úselo shopt -upara deshabilitar.

Otra forma es cambiar la configuración regional a C. Puede hacerlo temporalmente usando una subshell:

$ ( LC_ALL=C ; printf '%s\n' [A-Z]*; )

Obtendrá los resultados que necesita, y cuando el subconjunto finalice, la configuración regional del intérprete principal no cambiará a lo que era antes.

Otra alternativa es en lugar de [A-Z]usar la expansión de llaves {A..Z}junto con la nullglobopción bash shopt.

Al habilitar la nullglobopción, si un patrón no coincide durante la expansión del nombre de ruta, se devuelve una cadena nula en lugar del patrón en sí.
Como resultado, este funcionará como se esperaba:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
George Vasiliou
fuente
2
Perfecto gracias. No puedo usar [[:upper:]]porque en realidad solo quiero parte del alfabeto, pero esto funciona.
rosuav
1
@rosuav Bienvenido. Verifique también la alternativa de sub shell.
George Vasiliou
"Si está habilitado es igual a la configuración regional C" , ¿quiere decir que afecta a la configuración regional utilizada para el globbing y nada más? (Un enlace de referencia hubiera sido útil; lo mejor que puedo encontrar es gnu.org/software/bash/manual/html_node/Pattern-Matching.html , pero hubiera preferido una lista de todas las opciones de shell, pero faltan globasciiranges de gnu.org/software/bash/manual/html_node/… ; también la pregunta unix.stackexchange.com/questions/227070/… maneja este problema ampliamente.) También desde la versión 4.3.
PJTraill
@PjTrail Vea mi edición con un enlace de referencia a todas las opciones de compras. También puede ejecutar man bashen su terminal y buscar (usando /) para globasciiranges.
George Vasiliou
¿No LC_ALL=C printf '%s\n' [A-Z]*funcionaría para su segunda solución, sin una subshell? Por cierto: hay un error tipográfico: nullblogpero hay muy pocos caracteres para que pueda corregirlo.
Joe
5

Puede escribir todas las letras mayúsculas muy bien como:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

o use puede usar la clase de caracteres nombrada [:upper:]para representar todas las letras mayúsculas en su actual locale:

[[:upper:]]*

Como habrás notado, mientras usas el rango, [B-C]las mayúsculas y minúsculas para el mismo carácter alfabético se organizan de forma adyacente (de acuerdo con el orden de clasificación del locale)

heemayl
fuente
3

La inclusión de caracteres "no intuitivos" en los rangos de caracteres, como la inclusión de letras minúsculas en un rango cuyos límites son letras mayúsculas, se debe a la LC_COLLATEconfiguración regional. LC_COLLATEse supone que indica el orden de clasificación, pero hace un mal trabajo (la clasificación de cadenas es más compleja de lo que pueden hacer las configuraciones regionales) y es mejor sin ella. Recomiendo eliminar LC_COLLATEde su configuración regional. Si está configurando LANG, o LANGUAGE, no hacer eso y establecer sólo los que necesita: LC_CTYPE, LC_MESSAGES, LC_TIME.

Para obtener más información sobre las configuraciones regionales, consulte ¿En qué debo configurar mi configuración regional y cuáles son las implicaciones de hacerlo? y establezca LC_ * pero no LC_ALL

Para obtener resultados confiables en un script, independientemente de la configuración del usuario, establezca LC_ALL=C.

Gilles 'SO- deja de ser malvado'
fuente
0

Conjunto:

shopt -u nocaseglob

Desde la página de manual de bash:

>     nocaseglob
>         If  set,  bash matches filenames in a case-insensitive
>         fashion when performing pathname expansion (see Pathname
>          Expansion above).

Si establece 'globasciiranges', no sé qué pasará con los personajes que no son ascii como utf-8

Udi
fuente
0

echo [cC] * debe hacer lo que quiera, de manera similar [A-Za-z] *

Estoy aquí porque el bloqueo en mi sistema ha dejado de ser sensible a mayúsculas y minúsculas, por lo que muchos de mis scripts ya no funcionan como deberían :-(

usuario208007
fuente
Eso es lo opuesto a lo que estoy viendo. Pero revise las otras respuestas para obtener sugerencias.
rosuav