Unix komut satırında Unicode Normalleştirme Formları arasında dönüştürme


22

Unicode'da, bazı karakter kombinasyonlarının birden fazla gösterimi vardır.

Örneğin, ä karakteri şu şekilde temsil edilebilir:

  • "ä", yani U + 00E4 kod noktası ( c3 a4UTF-8 kodlamasında iki bayt ) veya
  • "ä", bu iki kod noktasıdır U + 0061 U + 0308 ( 61 cc 88UTF-8'de üç bayt ).

Unicode standardına göre, iki temsil eşdeğerdir ancak farklı "normalizasyon formlarında", bkz. UAX # 15: Unicode Normalizasyon Formları .

Unix araç kutusu her türlü metin dönüştürme aracına sahiptir, sed , tr , iconv , Perl akla geliyor. Komut satırında hızlı ve kolay NF dönüşümünü nasıl yapabilirim?


2
Perl için bu tür bir şey yapması gereken bir "Unicode :: Normalization" modülü var gibi görünüyor: search.cpan.org/~sadahiro/Unicode-Normalize-1.16/Normalize.pm
goldilocks

bir CLI olsaydı @goldilocks… Yani, demek istediğim perl -MUnicode::Normalization -e 'print NFC(… şimdi buraya ne gelirse…
mirabilos

Yanıtlar:


20

uconvYardımcı programı ICU'dan kullanabilirsiniz . Normalleştirme , harf çevirisi ( -x) ile sağlanır .

$ uconv -x any-nfd <<<ä | hd
00000000  61 cc 88 0a                                       |a...|
00000004
$ uconv -x any-nfc <<<ä | hd
00000000  c3 a4 0a                                          |...|
00000003

Debian, Ubuntu ve diğer türevleri üzerinde uconvolan libicu-devpaket. Fedora, Red Hat ve diğer türevlerde, BSD limanlarında ise icupakette.


Bu işe yarar, teşekkürler. Yine de bir 30M dev kütüphanesini yanına yüklemelisin. Daha da kötüsü, Uconv'un kendisi için uygun belgeleri bulamadım: Nerede buldun any-nfd? Görünüşe göre bu aracın gelişimi terk edilmiş, son güncelleme 2005’te yapıldı.
Eylül’de

2
@ glts Ben any-nfdtarafından görüntülenen listede göz atarak buldum uconv -L.
Gilles 'SO- kötülük olmayı'

Ubuntu kullanarak Açık sudo apt install icu-devtoolsçalıştırmak için uconv -x any-nfc, ama en basit sorunu çözmek değil , örneğin bir bugText.txt dosya "Iglesias, Bad-á, Good-á" tarafından dönüştürülen uconv -x any-nfc bugText.txt > goodText.txtfiyatının aynı metin.
Peter Krauss

7

Python, unicodedatastandart kütüphanesinde, Unicode gösterimlerini unicodedata.normalize()işlev yoluyla çevirmeyi sağlayan bir modüle sahiptir :

import unicodedata

s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2) 
print(ascii(t1)) 

t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)
print(ascii(t3))

Python 3.x ile çalışan:

$ python3 test.py
True
'Spicy Jalape\xf1o'
True
'Spicy Jalapen\u0303o'

Python bir kabuk için uygun değil, ancak harici script oluşturmak istemiyorsanız yapılabilir:

$ python3 -c $'import unicodedata\nprint(unicodedata.normalize("NFC", "ääääää"))'
ääääää

Python 2.x için kodlama satırı ( # -*- coding: utf-8 -*-) eklemeli ve dizeleri u karakterli Unicode olarak işaretlemelisiniz:

$ python -c $'# -*- coding: utf-8 -*-\nimport unicodedata\nprint(unicodedata.normalize("NFC", u"ääääää"))'
ääääää

3

Aracı hexdump ile kontrol edin:

echo  -e "ä\c" |hexdump -C 

00000000  61 cc 88                                          |a..|
00000003  

iconv ile dönüştürün ve hexdump ile tekrar kontrol edin:

echo -e "ä\c" | iconv -f UTF-8-MAC -t UTF-8 |hexdump -C

00000000  c3 a4                                             |..|
00000002

printf '\xc3\xa4'
ä

2
Bu sadece macOS'ta çalışır. Linux'ta, FreeBSD'lerde, vs.'de 'utf-8-mac' yoktur. Ayrıca, bu kodlamayı kullanarak ayrıştırma özelliği belirtilenlere uymaz (gerçekte macOS dosya sistemi normalleştirme algoritmasını izler). Daha çok bilgi: search.cpan.org/~tomita/Encode-UTF8Mac-0.04/lib/Encode/...
antonone

@antonone, soruda belirtilen herhangi bir işletim sistemi olmamasına rağmen adil olmak üzere.
roaima

1
@roaima Evet, bu yüzden cevabın Unix / Linux tabanlı tüm sistemlerde çalışması gerektiğini düşündüm. Yukarıdaki cevap sadece macOS'ta çalışır. Eğer biri macOS'a özel bir cevap arıyorsa, kısmen çalışacaktır. Sadece şunu belirtmek istedim, çünkü geçen gün neden utf-8-macLinux'ta olmadığımı ve bunun normal olup olmadığını merak ederek biraz zaman kaybettim .
antonone

3

Bütünlüğü sağlamak için perl:

$ perl -CSA -MUnicode::Normalize=NFD -e 'print NFD($_) for @ARGV' $'\ue1' | uconv -x name
\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}
$ perl -CSA -MUnicode::Normalize=NFC -e 'print NFC($_) for @ARGV' $'a\u301' | uconv -x name
\N{LATIN SMALL LETTER A WITH ACUTE}

2

Coreutils uygun almak için bir yama vardır unorm. 4 bayt wchars benim için iyi çalışıyor. takip edin http://crashcourse.housegordon.org/coreutils-multibyte-support.html#unorm Kalan sorun, kodotemleri yukarıdan dönüştürmek gereken 2 baytlık wchar sistemleri (cygwin, windows, aix ve solaris). uçaklar yedek çiftler halinde ve tersi de geçerlidir ve altta yatan libunistring / gnulib henüz bununla başa çıkamaz.

perl, unicharscmdline üzerinde çeşitli normalizasyon formları da yapan bir araca sahiptir . http://search.cpan.org/dist/Unicode-Tussle/script/unichars


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.