“ wc -c ” и “ wc -m ” команда в Linux

Вам не нужно заботиться об этих сообщениях разработчика и предупреждении.

Вы как пользователь должны открывать приложение GTK (например, firefox) без перенаправления сообщений в окно терминала следующим образом:

[F1]
1
задан 28 July 2016 в 14:41

2 ответа

$ locale charmap
UTF-8

В моей текущей среде набор символов - UTF-8, то есть символы кодируются с 1 по 4 байта на символ (хотя из-за того, что исходное определение UTF-8 допускает кодовые коды символов до 0x7fffffff, большинство инструментов распознают байтовые последовательности UTF-8 длиной до 6 байтов).

В этом наборе символов доступны все символы из Unicode, a закодирован как значение байта 65, а 乕 как 3 байта 228 185 149 и é в качестве двух байтовых последовательностей 195 169.

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

Теперь:

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

Я изменил свою среду , где набор символов теперь ISO-8859-15 (другие вещи, такие как язык, символ валюты, формат даты, также были изменены, коллекция этих региональных настроек упоминается как локаль). Мне нужно запустить новый эмулятор терминала в этой среде, чтобы он адаптировал его визуализацию символов к новому языку.

ISO-8859-15 - это набор символов с одним байтом, что означает, что он имеет только 256 символов (на самом деле даже меньше, чем на самом деле покрыты). Этот характерный набор символов используется для языков Западной Европы, поскольку он охватывает большинство его языков (и символ евро).

Он имеет символ a с байтовым значением 65, как в UTF-8 или ASCII , он также имеет символ é (как обычно используется на французском или испанском языках, например), но с байтом 233, он не имеет символа..

В этой среде wc -c и wc -m всегда будет давать тот же результат.

В Ubuntu, как и в большинстве современных Unix-подобных систем, по умолчанию обычно используется UTF-8, поскольку он является единственным поддерживаемым набором символов (и кодировкой), который охватывает весь Unicode range.

Существуют другие многобайтовые кодировки символов, но они не так хорошо поддерживаются на Ubuntu, и вам нужно пройти через обручи, чтобы иметь возможность генерировать локаль с ними, и если вы это сделаете, вы обнаружите, что многие вещи не работают должным образом.

Таким образом, на Ubuntu наборы символов либо однобайтовые, либо UTF-8.

Теперь несколько больше примечаний:

В UTF-8 не все байты e последовательностей образуют действительные символы. Например, все символы UTF-8, которые не являются ASCII, формируются с байтами, все из которых имеют 8-й бит, но где только первый имеет 7-й бит.

Если у вас есть последовательность байты с 8-м битом, ни один из которых не имеет 7-го бита, то это не может быть переведено на символ. И это когда у вас возникают проблемы и несоответствия, поскольку программное обеспечение не знает, что с ними делать. Например:

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

wc и grep не найти там никакого символа, но:

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

bash находит 3. Когда он не может отобразить последовательность байтов для символа, он считает каждый байт символом.

Он может стать еще более сложным, поскольку в Unicode есть кодовые страницы, которые недопустимы как символы, а некоторые, которые являются locale [!d4 ], и в зависимости от инструмента их кодировка UTF-8 может считаться или не считаться символом.

Еще одна вещь, которую следует учитывать, - это различие между символом и графемом и как они отображаются.

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

Там у нас есть код 3 символа, так как 6 байтов отображаются как один графем, потому что у нас есть 3 символа вместе (один базовый символ, сочетание острого акцента и комбинация окружающего круга ).

Реализация GNU wc, найденная на Ubuntu, имеет переключатель -L, чтобы указать ширину отображения самой широкой строки на входе:

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

Вы также обнаружите, что некоторые символы занимают 2 ячейки в этом как наш 乕 символ сверху:

$ echo 乕 | wc -L
2

В заключение: в более диком слове байт, символ и графх не обязательно одинаковы.

2
ответ дан 23 May 2018 в 07:43

Разница между wc -c и wc -m заключается в том, что в локали с многобайтовыми символами (например, UTF8) предыдущий подсчитывает байты, а последний подсчитывает символы. Рассмотрим следующий файл:

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

(для тех, кто не говорит UTF8, это буквы «x», «y» и «π», а затем новая строка). Он имеет длину 5 байтов:

$ wc -c dummy.txt 
5 dummy.txt

, но всего четыре символа:

$ wc -m dummy.txt 
4 dummy.txt
1
ответ дан 23 May 2018 в 07:43
  • 1
    Или, рассмотрите даже UTF-32, где каждый символ имеет 4 байта. – Jörg W Mittag 29 July 2016 в 13:26

Другие вопросы по тегам:

Похожие вопросы: