Чувствительность к регистру в квадратных скобках

10

Обычно, bash globbing чувствителен к регистру:

$ 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

Использование квадратных скобок, кажется, не меняет это:

$ 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

Это все еще не меняет его, если используется дефис:

$ 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

Но буквы перемежаются:

$ 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

Это говорит о том, что дефис использует порядок локали "AaBbCcDd". Итак: есть ли способ для glob для всех файлов, которые начинаются с заглавной буквы?

rosuav
источник
3
Также обратите внимание на то, что [AZ] соответствует каждой строчной букве, кроме «z»!
PJTraill

Ответы:

12

В bash версии 4.3 и более поздних версиях существует опция покупки globasciiranges:

По словам собравшихся встроенных гну man-страниц :

globasciiranges
Если установлено, выражения диапазона, используемые в выражениях скобок сопоставления с образцом (см. Сопоставление с образцом), ведут себя так же, как в традиционном языке C при выполнении сравнений. То есть последовательность упорядочения текущей локали не учитывается, поэтому «b» не будет сопоставлять «A» и «B», а символы ASCII в верхнем и нижнем регистре будут сопоставляться вместе.

В результате вы можете

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

Используйте shopt -uдля отключения.

Другой способ - изменить локаль на C. Вы можете сделать это временно, используя подоболочку:

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

Вы получите нужные вам результаты, и когда суб-оболочка будет завершена, локаль вашей основной оболочки останется неизменной, какой была раньше.

Другой вариант - вместо [A-Z]использования расширения скобок {A..Z}вместе с nullglobопцией bash shopt.

При включении этой nullglobопции, если шаблон не сопоставляется во время раскрытия имени пути, вместо самого шаблона возвращается пустая строка.
В результате этот будет работать как ожидалось:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
Георгий Василиу
источник
2
Отлично, спасибо. Я не могу использовать, [[:upper:]]потому что я на самом деле хочу только часть алфавита, но это работает.
Росаав
1
@rosuav Добро пожаловать. Проверьте также альтернативу sub shell.
Георгий
«Если включено, то равно языку C» - вы имеете в виду, что это влияет на язык, используемый для сглаживания, и ничего больше? (Ссылочная ссылка была бы полезна - лучшее, что я могу найти, это gnu.org/software/bash/manual/html_node/Pattern-Matching.html , но я бы предпочел список всех параметров оболочки, но globasciiranges отсутствует от gnu.org/software/bash/manual/html_node/… ; также вопрос unix.stackexchange.com/questions/227070/… подробно решает эту проблему.) Также из версии 4.3.
PJTraill
@PjTrail Смотрите мои изменения со ссылкой на все варианты покупок. Также вы можете запустить man bashв своем терминале и искать (используя /) globasciiranges.
Георгий
Не подойдет ли LC_ALL=C printf '%s\n' [A-Z]*ваше второе решение - без подоболочки? КСТАТИ: есть опечатка nullblog, но я слишком мало символов, чтобы исправить это.
Джо
5

Вы можете написать все заглавные буквы просто так:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

or use может использовать именованный класс символов [:upper:]для представления всех заглавных букв в вашем текущем locale:

[[:upper:]]*

Как вы заметили, при использовании диапазона, например, [B-C]верхний и нижний регистры для одного и того же буквенного символа располагаются рядом (в соответствии с порядком сортировки locale).

heemayl
источник
3

Включение «неинтуитивных» символов в диапазоны символов, например включение строчных букв в диапазон, границы которого являются заглавными буквами, обусловлено LC_COLLATEнастройкой локали. LC_COLLATEдолжен указывать порядок сортировки, но он плохо справляется с этим (сортировка строк более сложна, чем то, что может сделать локаль), и вам лучше без него. Я рекомендую удалить LC_COLLATEиз ваших региональных настроек. Если вы устанавливаете LANG, или LANGUAGE, не делают этого и установить только те , что вам нужно: LC_CTYPE, LC_MESSAGES, LC_TIME.

Для получения дополнительной информации о региональных настройках см. Раздел « Что я должен установить для своей региональной настройки» и каковы последствия этого? и установите LC_ *, но не LC_ALL

Чтобы получить достоверные результаты в скрипте независимо от настроек пользователя, установите LC_ALL=C.

Жиль "ТАК - перестань быть злым"
источник
0

Установлен:

shopt -u nocaseglob

Со страницы руководства bash:

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

Если вы установите 'globasciiranges', я не знаю, что будет с не-ascii символами, такими как utf-8

Уди
источник
0

echo [cC] * должен делать то, что вы хотите, аналогично [A-Za-z] *

Я здесь, потому что глобализация в моей системе перестала быть чувствительной к регистру, поэтому загрузка моих скриптов больше не работает так, как должна :-(

user208007
источник
Это противоположно тому, что я вижу. Но проверьте другие ответы на предложения.
Розав