У меня есть несколько очень больших XML-файлов, и я пытаюсь найти строки, которые содержат символы неASCII. Я попробовал следующее:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
Но это возвращает каждую строку в файле, независимо от того, содержит ли строка символ в указанном диапазоне.
У меня есть синтаксис неправильно, или я делаю что-то еще неправильно? Я также попробовал:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(и с одинарными и с двойными кавычками, окружающими шаблон).
Странно, но мне пришлось делать это сегодня! В итоге я использовал Perl, потому что не мог заставить grep/egrep работать (даже в режиме -P). Что-то вроде:
cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'
Для символов юникода (например, \u2212
в примере ниже) используйте следующее:
find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;
У меня работает следующее:
grep -P "[\x80-\xFF]" file.xml
Не-ASCII символы начинаются с 0x80 и переходят в 0xFF при просмотре байтов. Grep (и семейство) не обрабатывают Unicode для объединения многобайтовых символов в единый объект для сопоставления регулярных выражений, как вам кажется. Параметр -P
в моем grep позволяет использовать экранирование \ xdd
в классах символов для выполнения того, что вы хотите.
Самый простой способ - определить символ, отличный от ASCII ... как символ, который не является символом ASCII.
LC_ALL=C grep '[^ -~]' file.xml
При необходимости добавьте табуляцию после ^
.
Настройка LC_COLLATE = C
позволяет избежать неприятных сюрпризов о значении диапазонов символов во многих регионах. Установка LC_CTYPE = C
необходима для сопоставления однобайтовых символов - иначе команда пропустит недопустимые последовательности байтов в текущей кодировке. Установка LC_ALL = C
полностью исключает эффекты, зависящие от локали.