Инструмент Unix для вывода первых n символов в кодированном файле UTF-8
Я хочу напечатать первые 1000 символов в файле в кодировке UTF-8. Я знаю, что инструмент head может печатать первые n байтов файла, но он может вырезать символ в середине, так что в конце я получаю искаженный вывод.
Для этого я могу написать программу на awk, но могу ли я узнать, есть ли более простой способ?
PS. Я считаю необоснованным, что голова и хвост не поддерживают кодировку символов (переменная среды LANG), в то время как другие инструменты, такие как cut, wc, sed и awk, поддерживают кодировку символов.
2 ответа
Не уверен, что это проще, но это мой путь:
cat file | iconv -t UTF-32 | head -c $[1000 *4+4] | iconv -f UTF-32
Это преобразует Unicode в форму с фиксированной шириной, так что 1000 всегда будет представлять целые символы.
Просто чтобы предоставитьawk
Как сказал ОП другим сотрудникам Google, давайте проверим 5 гласных с острым ударением :
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
выбирает первые три символа и выводит желаемое:
áéí
Каждый из этих символов UTF-8 имеет длину 2 байта, мы можем проверить это с помощью:
printf 'áéíóú' | hd
который дает:
00000000 c3 a1 c3 a9 c3 ad c3 b3 c3 ba |..........|
0000000a
поэтому мы могли бы эквивалентно протестировать это как:
printf '\xc3\xa1\xc3\xa9\xc3\xad\xc3\xb3\xc3\xba' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
Если мы используем неправильную локаль, напримерC
который обрабатывает каждый байт отдельно:
printf 'áéíóú' | LC_CTYPE=C awk '{print substr($0,1,3);exit}' | hd
дает первые три байта:
c3 a1 c3
который отображается на терминале как:
á
с тех пор какc3
это мусор сам по себе.
Не уверен, как это можно сравнить сiconv
с точки зрения производительности для огромных входов. Но для мелочей это достаточно хорошо и просто.
Протестировано на Ubuntu 21.04.