Czułość wielkości liter w nawiasach kwadratowych

10

Zwykle w globowaniu bash rozróżniana jest wielkość liter:

$ 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

Używanie nawiasów kwadratowych nie zmienia tego:

$ 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

Nadal nie zmienia tego, jeśli używany jest łącznik:

$ 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

Ale litery są przeplatane:

$ 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

Sugeruje to, że łącznik używa kolejności ustawień regionalnych „AaBbCcDd”. Więc: czy istnieje sposób globowania dla wszystkich plików, które zaczynają się od dużej litery?

rosuav
źródło
3
Zauważ też, że [AZ] pasuje do każdej małej litery z wyjątkiem „z”!
PJTraill

Odpowiedzi:

12

W wersji bash 4.3 i nowszych dostępna jest opcja shopt o nazwie globasciiranges:

Według stron man wbudowanych w GNU :

globasciiranges
Jeśli ustawione, wyrażenia zakresów używane w wyrażeniach nawiasów dopasowujących wzorce (patrz Dopasowywanie wzorców) zachowują się tak, jak w tradycyjnych ustawieniach regionalnych C podczas porównywania. Oznacza to, że kolejność zestawiania bieżącego ustawienia narodowego nie jest brana pod uwagę, więc „b” nie będzie zestawiane między „A” i „B”, a znaki ASCII pisane wielkimi i małymi literami będą zestawiane razem.

W rezultacie możesz

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

Użyj shopt -udo wyłączenia.

Innym sposobem jest zmiana ustawień regionalnych na C. Możesz to zrobić tymczasowo za pomocą podpowłoki:

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

Otrzymasz potrzebne wyniki, a gdy skończona podpowłoka, ustawienia regionalne głównej powłoki pozostaną niezmienione w stosunku do tego, co było wcześniej.

Inną alternatywą jest zamiast [A-Z]używania nawiasów klamrowych {A..Z}razem z nullglobopcją bash shopt.

Po włączeniu nullglobopcji, jeśli wzorzec nie jest dopasowywany podczas rozwijania nazwy ścieżki, zwracany jest ciąg zerowy zamiast samego wzorca.
W rezultacie ten będzie działał zgodnie z oczekiwaniami:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
George Vasiliou
źródło
2
Perfekcyjnie, dzięki. Nie mogę użyć, [[:upper:]]bo tak naprawdę chcę tylko część alfabetu, ale to działa.
rosuav
1
@rosuav Witamy. Sprawdź także alternatywę dla sub-powłoki.
George Vasiliou,
„Jeśli włączone jest ustawienie regionalne C” - czy masz na myśli, że wpływa to na ustawienia narodowe używane do globowania i nic więcej? (Link referencyjny byłby pomocny - najlepsze, co mogę znaleźć, to gnu.org/software/bash/manual/html_node/Pattern-Matching.html , ale wolałbym listę wszystkich opcji powłoki, ale brakuje globasciiranges z gnu.org/software/bash/manual/html_node/… ; także pytanie unix.stackexchange.com/questions/227070/... obsługuje ten problem w szerokim zakresie.) Również od wersji 4.3.
PJTraill
@PjTrail Zobacz moją edycję z linkiem referencyjnym do wszystkich opcji shopt. Możesz także uruchomić man bashw swoim terminalu i wyszukać (za pomocą /) globasciiranges.
George Vasiliou,
Nie LC_ALL=C printf '%s\n' [A-Z]*działałoby w przypadku drugiego rozwiązania - bez podpowłoki? BTW: jest literówka: nullblogale jest za mało znaków, żeby to poprawić.
Joe
5

Możesz pisać wszystkie wielkie litery, tak jak:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

lub użyj może użyć nazwanej klasy znaków [:upper:]do przedstawienia wszystkich wielkich liter w twoim bieżącym locale:

[[:upper:]]*

Jak zauważyłeś, przy użyciu zakresu, takiego jak [B-C]wielka i mała litera dla tego samego znaku alfabetu, układane są obok siebie (zgodnie z porządkiem sortowania locale).

heemayl
źródło
3

Włączanie „nieintuicyjnych” znaków w zakresach znaków, na przykład uwzględnianie małych liter w zakresie, którego granice są wielkimi literami, wynika z LC_COLLATEustawienia regionalnego. LC_COLLATEma wskazywać kolejność sortowania, ale robi z tym kiepską robotę (sortowanie ciągów jest bardziej skomplikowane niż to, co mogą robić lokalizacje) i lepiej bez niego. Zalecam usunięcie LC_COLLATEz ustawień regionalnych. Jeśli jesteś ustawienie LANG, albo LANGUAGEnie rób tego i ustawić tylko te potrzebne są: LC_CTYPE, LC_MESSAGES, LC_TIME.

Aby uzyskać więcej informacji na temat ustawień narodowych, zobacz Co należy ustawić w moich ustawieniach regionalnych i jakie są tego konsekwencje? i ustaw LC_ *, ale nie LC_ALL

Aby uzyskać wiarygodne wyniki w skrypcie niezależnie od ustawień użytkownika, ustaw LC_ALL=C.

Gilles „SO- przestań być zły”
źródło
0

Zestaw:

shopt -u nocaseglob

Ze strony podręcznika użytkownika bash:

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

Jeśli ustawisz „globasciiranges”, nie wiem, co stanie się z postaciami nie-ascii, takimi jak utf-8

Udi
źródło
0

echo [cC] * powinno robić, co chcesz, podobnie [A-Za-z] *

Jestem tutaj, ponieważ globowanie w moim systemie właśnie przestało rozróżniać małe i wielkie litery, więc mnóstwo moich skryptów nie działa już tak, jak powinny :-(

użytkownik208007
źródło
To jest przeciwieństwo tego, co widzę. Ale sprawdź inne odpowiedzi na sugestie.
rosuav,