Linux'da “wc -c” ve “wc -m” komutu


24

Bir metin dosyasına sahibim, içeriği:

i k k

Ben kullandığınızda wc -mbu dosyada karakter numaralarını saymak, sonucudur 7 .

Soru 1: Fakat neden 7 aldım , “ satır sonu ” karakterini saydığını varsayarak “ 6 ” alamamalı mıyım?

Soru 2: Tam olarak nasıl wc -mçalışır?

Soru 3: Kullandığımda wc -c(bayt sayıları saymak için), aynı sonucu aldım wc -m, yani iki farklı seçeneğe sahip olmanın anlamı nedir? Tamamen aynı işi yapıyorlar, değil mi? Değilse, fark nedir ve nasıl wc -cçalışır?



1
Eğer Windows CRLF satır sonları ile Windows geldi, ayrıca 7 olabilir
Chris H

Yanıtlar:


36

Gerçekten orada sadece 6 karakter olmalı. Koşmayı dene

cat -A filename

Dosyanızın yazdırılmayan karakterlerini görmek için. Fazladan bir şeyin olmalı. Tıpkı seninki gibi bir dosya yaparsam

i k k$

Bir boşluk bıraktın mı? Bu 7 olacaktır: i k k $ya da belki de yeni bir hattı var:

i k k$
$

aynı zamanda 7

Dediğin gibi

wc -m

karakterleri sayar ve

wc -c

bayt sayar. Tüm karakterleriniz ASCII karakter kümesinin bir parçasıysa, karakter başına sadece 1 bayt olacak, böylece her iki komuttan da aynı sayıyı alacaksınız.

ASCII olmayan karakterlerle bir dosyada deneyin:

$ echo ك > testfile
$ wc -m testfile
2 testfile
$ wc -c testfile
3 testfile

Aha! Şimdi karakterlerden daha fazla bayt.


3
" Cat-A " komutunu kullandım ve sonunda " satır sonu " karakterinden ( $ ) önce bir boşluk bıraktığımı öğrendim . Bu yüzden 6 yerine 7 aldım. Teşekkürler, " kedi-A " çok yardımcı oldu.
SWIIWII

2
@SWIIWII Evet, cevabımı muhtemelen olacağını düşündüğüm gibi ekledim :)
Zanna

1
newline karakteri de sayıldı. Görünmez olsa bile, yine de bir karakterdir ve dosyada bir veri yığını olarak sayılır. Kedinin iyi kullanımı -Bu arada. Bir kez de aynı şeyi yapmak için hexdump veya xxd kullanabilirsiniz
Sergiy Kolodyazhnyy

@Serg evet, ve cat -Abunu da gösterecekti. Cevabımı ekledim, teşekkürler :)
Zanna

@SWIIWII `likethis`okunabilir hale getirmek için backticks kodunu koy , cesur yapma
phuclv

2
$ locale charmap
UTF-8

Geçerli ortamımda, karakter kümesi UTF-8'dir, yani karakterler karakter başına 1 - 4 baytla kodlanır (ancak UTF-8'in izin verdiği karakter kodunun orijinal tanımı 0x7fffffff'e işaret ettiğinden, çoğu araç UTF'yi tanır. 6 bayta kadar 8 bayt dizileri).

Bu karakter kümesinde, Unicode'un tüm karakterleri mevcuttur, a aörneğin bayt değeri 65, a 3 bayt 228 185 149 ve éiki bayt dizisi 195 169 olarak kodlanır .

$ printf 乕 | wc -mc
  1       3
$ printf a | wc -mc
  1       1

Şimdi:

$ export fr_FR.iso885915@euro
$ locale charmap
ISO-8859-15

Ben karakter kümesi şimdi ISO-8859-15 benim ortamı, modifiye ettik (dil, para birimi simgesi, tarih biçimi gibi diğer şeyler de modifiye edilmiş, bu bölgesel ayarların koleksiyonu olarak anılacaktır ediliyor yerel ayar ). Karakter oluşturmasını yeni yerel ayarlara uyarlayabilmesi için bu ortamda yeni bir terminal emülatörü başlatmam gerekiyor.

ISO-8859-15 tek baytlık bir karakter kümesidir, bu yalnızca 256 karaktere sahip olduğu anlamına gelir (aslında gerçekte kapsandığından daha az). Bu özel karakter seti, dillerinin çoğunu (ve euro simgesini) kapsadığı için Batı Avrupa dilleri için kullanılır.

Bu sahiptir aUTF-8 veya ASCII, o da var gibi bayt değeri 65 ile karakterini ékarakterini (yaygın olarak örneğin Fransızca veya İspanyolca kullanılır) ama bayt değeri 233 ile, bu乕karakteri yoktur.

Bu ortamda wc -cve wc -mher zaman aynı sonucu verecektir.

Çoğu Unix benzeri sistemde olduğu gibi Ubuntu'da da, varsayılan olarak Unicode serisinin tamamını kapsayan tek desteklenen karakter kümesi (ve kodlama) olduğu için genellikle UTF-8'dir.

Diğer çok baytlık karakter kodlamaları var, ancak Ubuntu'da iyi desteklenmiyorlar ve bunlarla bir yerel ayar oluşturabilmek için çemberlerden geçmek zorundasınız ve eğer yaparsanız, pek çok şeyin bu olmadığını göreceksiniz. düzgün çalışın.

Böylece Ubuntu'da geçerli olan karakter kümeleri ya tek baytlık, ya da UTF-8.

Şimdi, birkaç not daha:

UTF-8'de, tüm bayt dizileri geçerli karakterler oluşturmaz. Örneğin, ASCII olmayan tüm UTF-8 karakterleri, hepsinin 8. biti ayarlanmış, ancak yalnızca birincisinin 7. biti ayarlandığı baytlardan oluşur.

Hiçbiri 7. biti ayarlanmamış olan 8. biti ayarlanmış bir bayt dizisi varsa, bu bir karaktere çevrilemez. Ve o zaman, yazılımın bunlarla ne yapacağını bilmediğinden, problemler ve tutarsızlıklar yaşamaya başladığınızda. Örneğin:

$ printf '\200\200\200' | wc -mc
      0       3
$ printf '\200\200\200' | grep -q . || echo no
no

wcve greporada hiçbir karakter bulamazsınız:

$ x=$'\200\200\200' bash -c 'echo "${#x}"'
3

bash 3 bulur. Bir bayt dizisini bir karaktere eşleyemediğinde, her byte'ı bir karakter olarak görür.

Unicode'da karakter olarak geçersiz, bazılarında karakter olmayan kod noktaları bulunduğundan daha karmaşık hale gelebilir ve araca bağlı olarak UTF-8 kodlamaları karakter olarak kabul edilebilir veya olmayabilir.

Dikkate alınması gereken bir başka şey, karakter ve grafem arasındaki fark ve bunların nasıl oluşturulduğu.

$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
      3       6

Burada, bir karakter olarak işlenen 3 karakteri 6 bayt olarak kodladık, çünkü bir araya getirilmiş 3 karakterimiz var (bir temel karakter, bir araya gelen akut vurgu ve bir birleştirme dairesi).

wcUbuntu'da bulunan GNU uygulamasının -L, girdideki en geniş satırın ekran genişliğini size söyleyebilecek bir anahtarı vardır :

$ printf 'e\u301\u20dd\n' | wc -L
1

Ayrıca bazı karakterlerin yukarıdan karakterimiz gibi genişlik hesaplamasında 2 hücre işgal ettiğini göreceksiniz :

$ echo 乕 | wc -L
2

Sonuç olarak: Wilder kelimesinde, byte, karakter ve graphem mutlaka aynı değildir.


1

Arasındaki fark wc -cve wc -msüre ikincisi sayımları karakterler, baytlı karakterler (diyelim ki, UTF8), eski sayımları bayt olan bir yerel ayarda olduğudur. Aşağıdaki dosyayı göz önünde bulundurun:

$ hexdump -C dummy.txt 
00000000  78 79 cf 80 0a                                    |xy...|

(UTF8 bilmeyenler için, 'x', 'y' ve 'π' harfleri, ardından yeni bir satır). Beş bayt uzunluğunda:

$ wc -c dummy.txt 
5 dummy.txt

ancak yalnızca dört karakter uzunluğunda:

$ wc -m dummy.txt 
4 dummy.txt

Veya, her karakterin 4 bayt olduğu UTF-32'yi bile düşünün.
Jörg W Mittag
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.