Как я могу grep
для символа Unicode 'ZERO WIDTH SPACE' (U+200B) в Linux?
$ grep '%U200B' filename?
Сначала напечатаем одно:
$ printf %b '\u200b' | uniname
character byte UTF-32 encoded as glyph name
0 0 00200B E2 80 8B ZERO WIDTH SPACE
Теперь мы должны иметь возможность использовать тот же формат для его поиска (используя Bash):
$ printf %b '\u200b' | grep -q "$(printf %b '\u200b')"
$ echo $?
0
Хитрость в том, что printf %b
обрабатывает аргументы как закодированные символы, поэтому вы можете использовать \x
для печати однобайтовых символов и \u
* для печати многобайтовых символов.
Чтобы найти его в файле, просто сделайте это:
grep "$(printf %b '\u200b')" filename
* В спецификации POSIX не совсем понятно, как работает %b
. Страница printf
сообщает:«Спецификация преобразования% b [...] была добавлена здесь как переносимый способ обработки -escapes, развернутых в строковых операндах, как это предусмотрено утилитой echo», а страница echo
показывает единственный недокументированный пример ее использовать.
Тестовое задание:
$ printf %b '\u200b' > test.txt
$ grep -q "$(printf %b '\u200b')" test.txt
$ echo $?
0
Следующее, отлично работает. Я создал файл с BabelMap(Google) и использовал его вариант сохранения.
Создан файл с номерами строк 1-5, а в строке 4 добавлен пробел нулевой длины:
> hexdump testout.txt -C
00000000 31 0a 32 0a 32 0a 33 0a 34 20 e2 80 8b 0a 35 0a |1.2.2.3.4 ....5.|
00000010
Обратите внимание на кодировку utf8 символа 'e2808b' в файле.
Этот простой grep находит правильную строку:
> grep $'\u200b' testout.txt
4
> grep $'\u200b' testout.txt|hexdump -C
00000000 34 20 e2 80 8b 0a |4 ....|
00000006
FWIW, мои GREP_OPTIONS установлены: "--color = auto -I -D skip -d skip", но я не думаю, что какие-либо из них актуальны.
Вы также можете использовать регулярные выражения Perl с GNU grep
grep --perl-regexp '\x {200B}' filename
В macos
это сложнее, так как BSD grep, который поставляется с ним, не поддерживает многобайтовый режим. Однако GNU grep может быть установлен через Homebrew, где он доступен как ggrep
.