LINUX.ORG.RU

Почему grep не матчит utf-16 bom?

 , , , ,


0

2

Пример:

printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^\xff\xfe' || echo "false"

результат false

А если искать не первые BOM байты, то все нормально матчится, пример (поменял только паттерн в grep):

printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '\x48\x00' || echo "false"

результат успешный



Последнее исправление: rulin (всего исправлений: 1)

Хуже того:

printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^' || echo "false"
printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '\xff' || echo "false"
printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '\xfe' || echo "false"
printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '\x48' || echo "false"
printf '\xff\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '\x00' || echo "false"

из этих команд первые три не матчатся, последние две матчатся.

А ещё:

printf '\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^' || echo "false"
printf '\xff\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^' || echo "false"
printf '\xfe\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^' || echo "false"
printf '\xfd\x48\x00\x65\x00\x6c\x00\x6c\x00\x6f\x00' | grep -PUa '^' || echo "false"
первая и четвёртая матчатся, вторая и третья нет.

Почему всё так - не знаю. Подозрений два: 1) баг в grep с signed vs unsigned, 2) юникод как-то напакостил

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от rulin

Скорее, в работе не grep'а, а perl regular expression, это же отдельная библиотека (libpcre2). Видимо, она обрабатывает BOM по умолчанию, только LANG=C переключает это поведение. Или там срабатывает проверка, что BOM — это не корректная utf-8 строка. Точно не знаю, в исходники смотреть лень.

mky ★★★★★
()
Ответ на: комментарий от mky

срабатывает проверка, что BOM — это не корректная utf-8 строка

так и есть. grep работает в системной локали. поскольку там utf8, то он пытается перевести это в ютф-8 и у него не получается (или получается, но там мусор, который не матчится)

iSage ★★★★
()
Ответ на: комментарий от rulin

Перестает пытаться сматчить как utf8 (что, очевидно, неправильно, поскольку текст в utf-16) и начинает матчить побайтово.

Вообще есть более продвинутые grep-ы, которые умеют в кодировки

iSage ★★★★
()
Ответ на: комментарий от iSage

Перестает пытаться сматчить как utf8

несовсем понял, bom и текст из printf в utf16, паттерн в grep побайтовый (байты из utf16), где uft8? всмысле сам grep ожидает utf8 потомучто в локале utf8?

и начинает матчить побайтово.

а мне насамом деле и нужно было побайтово. Для этого есть чтото более подходящее, чем grep?

rulin
() автор топика
Ответ на: комментарий от rulin

А, я не допроверял. Ну без -P по крайней мере grep '^' не забагованный как -P который его теряет.

Не знаю что там продвинутого, мне всегда казалось что это ключ для перл-программистов которым этот формат привычнее, а по функционалу разницы нет.

Впрочем раз уже LANG=C подсказали то наверно не важно.

firkax ★★★★★
()