UTF-8 ile `cut -c` (` --characters ') kullanılamaz mı?


15

Komutun cut, seçeneğe -csahip baytlar yerine karakterler üzerinde çalışma seçeneği vardır -b. Ancak bu, en_US.UTF-8yerel olarak çalışmıyor gibi görünüyor :

İkinci bayt, ikinci ASCII karakterini verir (UTF-8'de aynı şekilde kodlanır):

$ printf 'ABC' | cut -b 2          
B

ancak UTF-8 yerel ayarında üç Yunanca olmayan ASCII olmayan karakterin ikincisini vermez:

$ printf 'αβγ' | cut -b 2         
�

Bu iyi - ikinci bayt .
Bunun yerine ikinci karaktere bakıyoruz :

$ printf 'αβγ' | cut -c 2 
�

Kırık görünüyor.
Bazı deneylerde, aralığın 3-4ikinci karakteri gösterdiği ortaya çıkıyor :

$ printf 'αβγ' | cut -c 3-4
β

Ancak bu, 3 ila 4 arasındaki baytlarla aynıdır:

$ printf 'αβγ' | cut -b 3-4
β

Yani UTF-8 için -cfazla değildir -b.

Yerel ayar UTF-8 için doğru değil, ancak karşılaştırma, wcbeklendiği gibi çalışır;
Genellikle -c( --bytes) seçeneği ile bayt saymak için kullanılır . (Kafa karıştırıcı seçenek adlarına dikkat edin.)

$ printf 'αβγ' | wc -c
6

Ancak, şu şekilde çalışan seçenek -m( --chars) ile karakterleri de sayabilir :

$ printf 'αβγ' | wc -m
3

Bu yüzden yapılandırmam iyi görünüyor - ama özel bir şey var cut.

Belki de UTF-8'i desteklemiyor? Ama aksi takdirde desteklemeye gerek olmazdı, çok baytlık karakterleri desteklemek için görünüyor -bve -c.

Yani ne yanlış? Ve neden?


Yerel ayar, söyleyebildiğim kadarıyla utf8 için doğru görünüyor:

$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Girdi, bayt bayt:

$ printf 'αβγ' | hd 
00000000  ce b1 ce b2 ce b3                                 |......|
00000006

İlginç! Görünüşe göre -caynı kodu kullanıyor -b. Kaynak koduna baktınız mı? Belki de -caslında bunun için bir ipucu bulabilirsiniz .
— michas

Yanıtlar:


13

Hangisini cutkullandığınızı söylemediniz , ancak GNU uzun seçeneğinden bahsettiğinizden beri --charactersbunun olduğunu varsayıyorum. Bu durumda, şu pasajainfo coreutils 'cut invocation' dikkat edin :

‘-c character-list’
‘--characters=character-list’

Yalnızca karakter listesinde listelenen konumlardaki karakterleri yazdırmak için seçin. Şimdilik aynı-b , ancak uluslararasılaşma bunu değiştirecek.

(vurgu eklendi)

Şu an için GNU cuther zaman tek baytlık "karakterler" olarak çalışır, bu nedenle gördüğünüz davranış beklenir.


POSIX için -bhem -cseçenekleri hem de seçenekleri desteklemek gerekir - cutçoklu bayt desteği olduğu ve düzgün çalıştıkları için GNU'ya eklenmediler , ancak POSIX uyumlu girişte hata vermemek için. Aynı -cşey en azından FreeBSD ve OS X'lerdecut olmasa da diğer bazı uygulamalarda da yapılmıştır .

Bu tarihi davranış arasında -c. çok baytlı karakterlerle çalışabilmek -biçin bayt rolünü üstlenmek üzere yeni eklendi -c. Belki birkaç yıl içinde sürekli olarak istenen şekilde çalışacaktır, ancak ilerleme tam olarak hızlı olmamasına rağmen (zaten on yıldan fazladır). GNU , dikey ve geçişe yardımcı olması amaçlanmış olsa bile cut , -nseçeneği henüz uygulamıyor . Nedenin ne olduğunu kesin olarak bilmememe rağmen, eski betiklerle ilgili olası uyum sorunları vardır.


1
iyi iş. GNU trbelgelerinde de aynı türden yorumlar bulacaksınız . ve taryanlış hatırlamıyorsam bile . Bence bu büyük bir proje.
— mikeserv

Unicode probelm için herhangi bir geçici çözüm var mı cut? Örneğin, yamalı kaynakların nereden indirilebileceği cut? Yoksa başka bir yardımcı program kullanmak daha mı kolay olur? ( grepaşağıdaki çözüm aralıklarla düzgün çalışmaz örneğin 5-8,44-49)
— dma_k

"GNU Coreutils'te çok baytlı ve unicode desteği ekleme çabalarına ilişkin rastgele notlar ve işaretçiler" başlıklı bu makaleye bakın :: crashcourse.housegordon.org/coreutils-multibyte-support.html
— myrdd

cut -cburada bazı alternatifler bulabilirsiniz : superuser.com/questions/506164/…
— myrdd

5

colrm(bir kısmı, util-linuxçoğu dağıtımda zaten kurulu olmalıdır) uluslararasılaşmayı çok daha iyi ele alıyor gibi görünüyor:

$ echo 'αβγ' | colrm 3
αβ
$ echo 'αβγ' | colrm 2
α

Numaralandırmaya dikkat edin: en fazla karakter yazdıracak şekilde colrm Nsütunları kaldıracak .NN-1

( kredi )


2

Birçok grepuygulama çok baytlı olduğundan, grep -obazı kullanımlarını simüle etmek için de kullanabilirsiniz cut -c.

$ echo Τηεοδ29 | grep -o '^..'
Τη
$ echo Τηεοδ29 | egrep -o '^..' | grep -o '.$'
η

cutAralıkları simüle etmek için nokta sayısını ayarlayın .

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.