LC_COLLATE karakter aralıklarını etkiler mi?


27

Harmanlama sırası, LC_COLLATEyalnızca bireysel karakterlerin sıralama düzenini değil, karakter aralıklarının anlamını da tanımlar. Yoksa öyle mi? Aşağıdaki pasajı göz önünde bulundurun:

unset LANGUAGE LC_ALL
echo B | LC_COLLATE=en_US grep '[a-z]'

Sezgisel, içeride Bdeğil [a-z], bu yüzden hiçbir şey çıkmamalı. Ubuntu 8.04 veya 10.04'te olan da budur. Ama Debian Lenny veya sıkmak çalışan bazı makinelerde, Baralık, çünkü bulunursa a-zaramda her şeyi içerir ave zbüyük harflerle dahil harmanlama amacıyla, içinde Baracılığıyla Z.

Test edilen tüm sistemler en_USoluşturulan yerel ayarlara sahiptir. Ayrıca yerel ayarları değiştirmeyi de denedim: Byukarıda eşleştirilen makinelerde , {en_{AU,CA,GB,IE,US},fr_FR,it_IT,es_ES,de_DE}{iso8859-1,iso8859-15,utf-8}Japonca (mevcut herhangi bir kodlamada) ve C/ hariç tüm yerel ayarlarda (çoğunlukla latin tabanlı: ayrıca Çin yerelleri) de aynı şey geçerli POSIX.

Karakter aralıkları , ASCII'nin ötesine geçtiğinizde normal ifadelerde ne anlama geliyor ? Bir yandan bazı Debian kurulumları, diğer yandan diğer Debian kurulumları ve Ubuntu arasında neden bir fark var? Diğer sistemler nasıl davranır? Kim haklı ve kime karşı bir hata bildirilmeli?

(Özellikle GNU libc tabanlı sistemlerde [a-z], en_USyerellerdeki gibi karakter aralıklarının davranışını özellikle sorduğumu unutmayın . Küçük harflerle veya ASCII küçük harflerini nasıl eşleştireceğinizi sormuyorum.)


İki Debian makineleri, birinde Bise [a-z]hem değil biri, çıkış LC_COLLATE=en_US locale -k LC_COLLATEDİR

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=1
collate-codeset="ISO-8859-1"

ve çıkış LC_COLLATE=en_US.utf8 locale -k LC_COLLATEIS

collate-nrules=4
collate-rulesets=""
collate-symb-hash-sizemb=2039
collate-codeset="UTF-8"

1
Kullandığım bir Debian Lenny örneğinde çoğalmıyor. en_USAncak, oluşturulan olup olmadığını kontrol etmedi .
alex,

1
@alex Yerel ayar oluşturulmadıysa, Cyerel ayar bir geri dönüş olarak kullanılır ve harmanlama sırası düz bayt değerlerdir, bu nedenle Beşleştirilmez. Çıktısında görünen bir yerel ayarda test edin locale -a.
Gilles 'SO- kötü olmayı bırak'

1
En_US'in en_US.utf8 ile aynı OLMADIĞINI ve tam olarak ne yüklediğinize bağlı olarak en_US.iso-8859-1 anlamına geldiğini unutmayın. Eğer en_US (soneksiz) yerel ayarın çıkışında görünmüyorsa -a aslında bu yerel ayarınız olmaz. LC_COLLATE = en_US yerel ayarı -k LC_COLLATE ne gösterir?
Neil Mayhew

1
Bu, o zamandan beri burada teorik bir sorudan ziyade pratik bir soruna yol açtı: Neden büyük harfler bir awk regex'ine bir dizi küçük harflerle dahil edildi?
Caleb

1
@isaac Maalesef 7 yıl sonra herhangi bir sorunlu sisteme erişimim yok. Hepsi yenilendi veya hizmetten alındı.
Gilles 'SO- kötülük'

Yanıtlar:


3

CYerel ayar dışında başka bir şey kullanıyorsanız , [a-z]bunlar yerel ayarlara bağlı olduklarından ve her zaman beklediğiniz sonuçları vermediklerinden, bu gibi aralıkları kullanmamalısınız . Karşılaştığınız durum sorununun yanı sıra, bazı yerel ayarlar karakterleri diakritik (örneğin, á ) ile temel karakter ( a ) ile aynı şekilde ele alır .

Bunun yerine, adlandırılmış bir karakter sınıfı kullanın:

echo B | grep '[[:lower:]]'

Bu her zaman yerel için doğru sonucu verecektir. Ancak, hem giriş metninizin hem de uygulamaya çalıştığınız testin anlamını yansıtmak için yerel ayarları seçmeniz gerekir.

Örneğin, belirli bir bayt değeri bulmanız gerekirse C, her zaman kullanılabilen yerel ayarı kullanın :

echo B | LANG=C grep '[a-z]'

Bu beklendiği gibi çalışmazsa, gerçekten bir hatadır.


Bunu biliyorum, istediğim bu değildi. Özellikle açık bir aralığın ne anlama geldiğini ve neden farklı dağıtımların (GNU libc ve GNU grep ile) farklı davranışları olduğunu soruyorum. (Oy vermedi, çünkü söylediğiniz şey doğru olsa bile, bu konu dışı.)
Gilles 'ÇÖZÜM'

1
Açıkçası, açık bir aralığın anlamının yerel ayarlara bağlı olduğu ve yerellerinin aynı şekilde tanımlanması için farklı sistemler gerekmediği, bu yüzden bu bir hata değil. Teknik olarak, sistemi kötüye kullanıyorsunuz, bu nedenle "tanımsız" davranışa geçerken şaşırmamalısınız. Ayrıca, birkaç kişi Debian sistemlerindeki davranışı çoğaltamayacaklarını belirtti, bu nedenle sisteminizde / sistemlerinde olağandışı bir şey olduğu görülüyor.
Neil Mayhew

1
Menzil davranışının yerellere bağlı olduğunu biliyorum. Nasıl soruyorum ve Glibc'i kullanan farklı sistemlerin (ve aynı Debian sürümünün farklı kurulumlarının bile) farklı davranışları olduğunu görünce şaşırdım. Sorumun çıktısını ekledim locale -k; Biri Baralıkta , diğeri olmayan iki Debian makinesinde aynıdır . BTW Her iki makinede de kök değilim (bu yüzden yönetici olarak yaptığım bir şey değil).
Gilles 'SO- kötülük yapmayı bırak'

echo "Baü" | LC_COLLATE=C grep -o '[[:lower:]]'döner aVE üederken echo "Baü" | LC_COLLATE=C grep -o '[a-z]'döner sadece a. Gözlerime göre "alt" OP'nin istediği şey değildi
Daniel Alder

Orijinal noktam yine de geçerli: Cyerelde olmadığınız sürece aralıkları kullanmayın . Bunun bir hata bildirmek isteyen OP ile ilgili olduğuna inanıyorum. Yerelde değilseniz C, aralıkları kullanmanın sonuçları son derece tahmin edilemez ve bu nedenle bir hata olarak kabul edilemez. Öte yandan, belirli bir bayt değeri bulmanız gerekiyorsa, yalnızca Cyerel ayarı kullanın . İkincil noktam, yerel ayarlarda küçük harfleri gerçekten aramak istiyorsanız karakter sınıfını kullanmaktı. OP bunu aramamış olsa bile, diğerleri bu soruyu bulursa kullanabilir.
Neil Mayhew

1

Düzenli ifadelerdeki aralıklar, harmanlama ayarını gözetmelidir. İlgili standart: http://pubs.opengroup.org/onlinepubs/007908799/xbd/re.html ("aralık ifadeleri" konusuna bakın). Bu nedenle ilgili yerel ayarın mantıklı bir tanımı verilmiş echo B | LC_COLLATE=en_US grep '[a-z]'olmalıdır B. Bunun neden bazen sizin için işe yaramadığını açıklayamıyorum, ancak düzgün bir şekilde kurulmuş ve yapılandırılmış antik olmayan bir sistemde karşılaştığımda çok şaşırırdım.


1
echo B | LC_COLLATE=en_US.utf8 grep '[a-z]' Ubuntu 12.04'te grep 2.10 ile hiçbir şey yazdırmıyor. Centos 6.5 üzerine grep 2.6.3 ile hiçbir şey basmaz. Grep 2.6.3 ile Debian 6.0.8 üzerinde çalışır.
Ian D. Allen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.