“туалет-c” и “туалет-m” управляют в Linux

У меня есть текстовый файл, его содержание:

i k k

Когда я использую wc -m для подсчета чисел символов на этот файл результат равняется 7.

Вопрос 1: Но почему я добирался 7, разве я не должен добираться "6", если это считает символ "конца строки"?

Вопрос 2: Как точно делает wc -m работа?

Вопрос 3: Когда я использую wc -c (для подсчета чисел байта), у меня есть тот же результат как wc -m, таким образом какой смысл того, чтобы иметь два различных вариантов? Они делают точно то же задание, не так ли? В противном случае, каково различие и как wc -c работы?

24
задан 28 July 2016 в 04:41

3 ответа

У Вас должно действительно быть только 6 символов там. Попытайтесь работать

cat -A filename

Для наблюдения непечатаемых символов файла. У Вас должно быть что-то дополнительное. Если я делаю файл точно так же, как Ваш, я вижу

i k k$

, Вы помещали пространство? Это сделало бы 7: i k k $ или возможно это имеет новую строку:

i k k$
$

, который равняется также 7

, Как Вы говорите

wc -m

символы количеств и

wc -c

байты количеств. Если все Ваши символы будут частью набора символов ASCII, то будет только 1 байт за символ, таким образом, Вы получите то же количество от обеих команд.

Примеряют файл с не символы ASCII:

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

Ага! Больше байтов, чем символы теперь.

36
ответ дан 23 November 2019 в 01:19

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

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

(для тех, кто не говорит UTF8, это - буквы 'x', 'y' и 'ПЂ', сопровождаемый новой строкой). Это пять байтов длиной:

$ wc -c dummy.txt 
5 dummy.txt

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

$ wc -m dummy.txt 
4 dummy.txt
1
ответ дан 23 November 2019 в 01:19
$ locale charmap
UTF-8

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

В том наборе символов все символы от Unicode доступны, a a кодируется как значение байта 65, a как 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.

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

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

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

В UTF-8 не все последовательности байта формируют допустимые символы. Например, все символы 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, которые недопустимы как символы и некоторых, которые являются несимволами, и в зависимости от инструмента, их кодировка UTF-8 может или не может быть рассмотрена как символ.

Другой вещью учесть является различие между символом и графемой, и как они представляются.

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

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

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

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

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

$ echo 乕 | wc -L
2

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

2
ответ дан 23 November 2019 в 01:19

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

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