У меня есть текстовый файл, его содержание:
i k k
Когда я использую wc -m
для подсчета количества символов в этом файле, результат 7 .
Вопрос 1: Но почему я получил 7, не должен ли я получить « 6 », полагая, что он считается символом « конец строки »?
Вопрос 2: Как именно wc -m
работает?
Вопрос 3: Когда я использую wc -c
(для подсчета байтовых чисел), я получаю тот же результат wc -m
, что и какой смысл иметь два разных варианта ? Они делают ту же самую работу, не так ли? Если нет, то какая разница и как wc -c
работает?
command-line
wc
SWIIWII
источник
источник
Ответы:
Там действительно должно быть всего 6 символов. Попробуйте запустить
Чтобы увидеть непечатные символы вашего файла. У тебя должно быть что-то дополнительное. Если я сделаю файл так же, как ваш, я вижу
Вы поставили пробел? Это сделало бы 7:
i k k $
или возможно это имеет новую строку:который также 7
Как ты говоришь
считает символы и
считает байты. Если все ваши символы являются частью набора символов ASCII, то для каждого символа будет только 1 байт, поэтому вы получите одинаковое количество от обеих команд.
Попробуйте файл с не ASCII-символами:
Ага! Теперь больше байтов, чем символов.
источник
cat -A
это тоже покажет. Я добавил к своему ответу, спасибо :)`likethis`
чтобы сделать его читабельным, не делайте его жирнымВ моей нынешней среде набор символов - это UTF-8, то есть символы кодируются от 1 до 4 байтов на символ (хотя, поскольку исходное определение допустимого кода символов UTF-8 указывает на 0x7fffffff, большинство инструментов распознает UTF- 8-байтовые последовательности до 6 байт).
В этом наборе символов доступны все символы из Unicode, например, a
a
кодируется как значение байта 65, a乕
как 3 байта 228 185 149 иé
как двухбайтовая последовательность 195 169.В настоящее время:
Я изменил свое окружение, в котором теперь используется набор символов ISO-8859-15 (другие вещи, такие как язык, символ валюты, формат даты, также были изменены, а коллекция этих региональных настроек называется локалью ). Мне нужно запустить новый эмулятор терминала в этой среде, чтобы адаптировать рендеринг символов к новой локали.
ISO-8859-15 является однобайтовым набором символов, что означает, что он имеет только 256 символов (фактически даже меньше, чем это фактически покрыто). Этот конкретный набор символов используется для языков Западной Европы, поскольку он охватывает большинство ее языков (и символ евро).
Он имеет
a
символ со значением байта 65, как в UTF-8 или ASCII, он также имеетé
символ (как обычно используется на французском или испанском языке, например), но со значением байта 233 у него нет символа 乕.В такой среде
wc -c
иwc -m
всегда будет давать один и тот же результат.В Ubuntu, как и в большинстве современных Unix-подобных систем, по умолчанию обычно используется UTF-8, поскольку это единственный поддерживаемый набор символов (и кодировка), который охватывает весь диапазон Unicode.
Существуют другие многобайтовые кодировки символов, но они не так хорошо поддерживаются в Ubuntu, и вы должны пройти через обручи, чтобы иметь возможность сгенерировать локаль с ними, и если вы это сделаете, вы обнаружите, что многие вещи не работать должным образом.
Таким образом, в Ubuntu наборы символов являются однобайтовыми или UTF-8.
Теперь еще несколько заметок:
В UTF-8 не все последовательности байтов образуют допустимые символы. Например, все символы UTF-8, которые не являются символами ASCII, формируются из байтов, для которых все установлены 8-м битами, но где только у первого установлен 7-й бит.
Если у вас есть последовательность байтов с установленным 8-м битом, ни у одного из которых не установлен 7-й бит, то это не может быть преобразовано в символ. И вот тогда у вас начинаются проблемы и несоответствия, так как программное обеспечение не знает, что с ними делать. Например:
wc
и неgrep
найти там никакого персонажа, кроме:bash
находит 3. Когда он не может отобразить последовательность байтов на символ, он считает каждый байт символом.Это может стать еще более сложным, поскольку в Unicode есть кодовые точки, которые являются недопустимыми в качестве символов, а некоторые не являются символами , и в зависимости от инструмента их кодировка UTF-8 может или не может рассматриваться как символ.
Еще одна вещь, которую следует принять во внимание, - это разница между характером и графическим символом и то, как они отображаются.
Там мы кодируем 3 символа как 6 байтов, отображаемых как один граф, потому что у нас есть 3 символа, объединенные вместе (один базовый символ, объединяющий острый акцент и объединяющий окружающий круг).
В реализации GNU,
wc
как в Ubuntu, есть-L
переключатель, показывающий ширину отображения самой широкой строки на входе:Вы также обнаружите, что некоторые символы занимают 2 ячейки в расчете ширины, как наш
乕
персонаж сверху:В заключение: в более диком слове байт, символ и графем не обязательно совпадают.
источник
Разница между
wc -c
иwc -m
заключается в том, что в локали с многобайтовыми символами (скажем, UTF8) первый считает байты, а второй - символы. Рассмотрим следующий файл:(для тех, кто не говорит на UTF8, это буквы 'x', 'y' и 'π', за которыми следует новая строка). Это пять байтов длиной:
но только четыре символа в длину:
источник