AWK GNU — разделение многобайтовых символьных строк с помощью Patsplit и Split

Я хотел бы знать, является ли следующее поведение надежным:

echo 😄 | gawk '{split($0,array,"."); print array[1] length(array);}'

Вывод: 😄1

против

echo 😄 | gawk '{patsplit($0,array,"."); print array[1] length(array);}'

Вывод: �4

patsplit работает над байтами, а split над символами, но я нигде не нашел этого задокументированного или обсуждаемого. Вопрос в том, могу ли я рассчитывать на такое поведение и где?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это потому, что split и patsplit — принципиально разные функции.

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

Все функции gawk, включая split и patsplit, работают с зависящими от локали символами, а не с байтами, согласно документации .

Кроме того, односимвольная строка, такая как ".", в качестве разделителя полей рассматривается буквально, а не как шаблон регулярного выражения (см. документацию по FS).

Поскольку во входной строке 😄 нет ., при вызове split с "." в качестве разделителя полей split видит только 1 поле.

А поскольку 😄 состоит из 4 байтов и, предположительно, вы установили локаль на основе байтов, например C, когда вы вызываете patsplit с "." в качестве шаблона поля, каждый . соответствует одному байту 😄, создавая массив размером 4.

Я прочитал fieldsep, is a regexp describing where to split string о разделении из документа GNU. Не знаю, почему документ говорит, что он работает с символами, символ 😄, состоящий из 1 символа и 4 байтов. Я проверил src, в поле field.c в do_patsplit вы можете увидеть, что он объявлен char *s;, что составляет байты.

Adam D. 15.08.2024 05:36

Пожалуйста, проверьте связанную документацию, где говорится: «Gawk понимает локали (см. Где вы находитесь, имеет значение) и выполняет всю обработку строк в виде символов, а не байтов». Объявление C может быть char *s;, если оно обрабатывается как символы с учетом локали.

blhsing 15.08.2024 05:37

Я это читал, но похоже, что это неправда.

Adam D. 15.08.2024 05:39

Опять же, тот факт, что тип параметра равен char *, не означает, что он логически обрабатывается побайтно. Если вы будете следовать коду, вы увидите, что он вызывает fpat_parse_field, который, в свою очередь, вызывает research, который обрабатывает строку как символы со всеми вспомогательными функциями, поддерживающими LC, в regcomp.c.

blhsing 15.08.2024 05:51

Да, я думаю, это последовательно. Я переключил разделитель разделения на пустую строку "", и оба возвращают количество байтов с помощью LC_ALL=C и количество символов с помощью LC_ALL=en_US.UTF-8. Возможно, документация могла бы прояснить ситуацию.

Adam D. 15.08.2024 05:54

Я не думаю, что документация должна быть более понятной, поскольку, заявляя, что все строки обрабатываются как символы с учетом локали, а не как байты, уже установлено, что символы эквивалентны байтам, когда вы устанавливаете LC_CTYPE как C (который принадлежит документации локали).

blhsing 15.08.2024 06:06

Если у вас есть многобайтовый символ и для LC_ALL установлено значение C, вы читаете байты в этот момент. Это семантический танец, в документации, вероятно, отражена поддержка многобайтовых символов как запоздалая мысль.

Adam D. 15.08.2024 23:06

скорее всего, это ошибка со стороны gawk.

RARE Kpop Manifesto 16.08.2024 04:01

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