Mam plik tekstowy, jego zawartość to:
i k k
Kiedy używam wc -m
do liczenia liczb znaków w tym pliku, wynik to 7 .
Pytanie 1: Ale dlaczego dostałem 7, czy nie powinienem dostać „ 6 ”, zakładając, że liczy się znak „ końca linii ”?
Pytanie 2: Jak dokładnie wc -m
działa?
Pytanie 3: Kiedy używam wc -c
(do liczenia liczb bajtowych), mam taki sam wynik jak wc -m
, więc jaki jest sens posiadania dwóch różnych opcji ? Wykonują dokładnie tę samą pracę, prawda? Jeśli nie, jaka jest różnica i jak wc -c
działa?
command-line
wc
SWIIWII
źródło
źródło
Odpowiedzi:
Rzeczywiście powinieneś mieć tam tylko 6 znaków. Spróbuj uruchomić
Aby zobaczyć niedrukowalne znaki z pliku. Musisz mieć coś dodatkowego. Widzę, że jeśli utworzę plik podobny do twojego
Czy umieściłeś miejsce? To dałoby 7:
i k k $
a może ma nową linię:czyli 7
Tak jak mówisz
liczy znaki i
liczy bajty. Jeśli wszystkie twoje znaki są częścią zestawu znaków ASCII, to będzie tylko 1 bajt na znak, więc otrzymasz taką samą liczbę z obu poleceń.
Wypróbuj plik zawierający znaki inne niż ASCII:
Aha! Więcej bajtów niż znaków.
źródło
cat -A
to pokaże. Dodałem do mojej odpowiedzi, dzięki :)`likethis`
aby był czytelny, nie pogrubiajW moim obecnym środowisku zestaw znaków to UTF-8, co oznacza, że znaki są kodowane od 1 do 4 bajtów na znak (chociaż ponieważ oryginalna definicja UTF-8 dopuszczała punkty kodowe do 0x7fffffff, większość narzędzi rozpoznaje UTF- 8 bajtów sekwencji do 6 bajtów).
W tym zestawie znaków wszystkie znaki z Unicode są dostępne, a
a
jest kodowany jako wartość bajtu 65, a乕
jako 3 bajty 228 185 149 i na przykładé
jako sekwencja dwóch bajtów 195 169.Teraz:
Zmodyfikowałem swoje środowisko, w którym zestaw znaków to teraz ISO-8859-15 (inne rzeczy, takie jak język, symbol waluty, format daty zostały również zmodyfikowane, a zbiór ustawień regionalnych nazywany jest ustawieniami regionalnymi ). Muszę uruchomić nowy emulator terminala w tym środowisku, aby dostosować renderowanie znaków do nowych ustawień regionalnych.
ISO-8859-15 jest jednobajtowym zestawem znaków, co oznacza, że ma tylko 256 znaków (w rzeczywistości nawet mniej niż te, które są rzeczywiście objęte). Ten szczególny zestaw znaków jest używany w językach Europy Zachodniej, ponieważ obejmuje większość jego języków (i symbol euro).
Ma
a
znak o wartości bajtu 65, jak w UTF-8 lub ASCII, ma równieżé
znak (jak powszechnie używany na przykład w języku francuskim lub hiszpańskim), ale o wartości bajtu 233 nie ma znaku 乕.W takim środowisku
wc -c
iwc -m
zawsze da taki sam rezultat.W Ubuntu, podobnie jak w większości współczesnych systemów uniksowych, domyślnie jest to UTF-8, ponieważ jest to jedyny obsługiwany zestaw znaków (i kodowanie) obejmujący cały zakres Unicode.
Istnieją inne wielobajtowe kodowania znaków, ale nie są one tak dobrze obsługiwane w Ubuntu i musisz przejść przez obręcze, aby móc wygenerować ustawienia narodowe za ich pomocą, a jeśli to zrobisz, przekonasz się, że wiele rzeczy nie działa poprawnie.
Tak więc w Ubuntu zestawy znaków są jednobajtowe lub UTF-8.
Teraz jeszcze kilka notatek:
W UTF-8 nie wszystkie sekwencje bajtów tworzą prawidłowe znaki. Na przykład wszystkie znaki UTF-8, które nie są znakami ASCII, są tworzone z bajtów, które mają ustawiony 8. bit, ale tylko pierwszy z nich ma ustawiony 7. bit.
Jeśli masz sekwencję bajtów z 8. bitowym zestawem, z których żaden nie ma 7. bitowego zestawu, to nie można go przetłumaczyć na znak. I wtedy zaczynają się problemy i niespójności, ponieważ oprogramowanie nie wie, co z nimi zrobić. Na przykład:
wc
igrep
nie znajdź tam żadnej postaci, ale:bash
znajduje 3. Gdy nie może odwzorować sekwencji bajtów na znak, uważa każdy bajt za znak.Może się jeszcze bardziej skomplikować, ponieważ w Unicode występują punkty kodowe, które są niepoprawne jako znaki, a niektóre, które nie są znakami , i w zależności od narzędzia ich kodowanie UTF-8 może, ale nie musi, być traktowane jako znak.
Inną rzeczą, którą należy wziąć pod uwagę, jest różnica między charakterem a grafhem oraz sposób ich renderowania.
Tam mamy 3 znaki jako 6 bajtów renderowane jako jeden grafhem, ponieważ mamy 3 znaki połączone razem (jeden znak podstawowy, łączący ostry akcent i łączący się okrąg).
Implementacja GNU,
wc
taka jak w Ubuntu, ma-L
przełącznik informujący o szerokości wyświetlania najszerszej linii na wejściu:Przekonasz się również, że niektóre postacie zajmują 2 komórki w tym obliczeniu szerokości, jak nasza
乕
postać z góry:Podsumowując: bardziej zwięźle, bajt, charakter i grafhem niekoniecznie są takie same.
źródło
Różnica między
wc -c
iwc -m
polega na tym, że w ustawieniach regionalnych ze znakami wielobajtowymi (powiedzmy UTF8), pierwsze z nich liczy bajty, a drugie zlicza znaki. Rozważ następujący plik:(dla tych, którzy nie mówią UTF8, są to litery „x”, „y” i „π”, po których następuje nowa linia). Ma pięć bajtów:
ale tylko cztery znaki:
źródło