Как я могу grep для всех символов, отличных от ASCII?
у меня есть несколько очень больших XML-файлов, и я пытаюсь найти строки, содержащие символы, отличные от ASCII. Я пробовал следующее:
grep -e "[x{00FF}-x{FFFF}]" file.xml
но это возвращает каждую строку в файле, независимо от того, содержит ли строка символ в указанном диапазоне.
у меня неправильный синтаксис или я делаю что-то еще неправильно? Я также пробовал:
egrep "[x{00FF}-x{FFFF}]" file.xml
(с одинарными и двойными кавычками, окружающими шаблон).
10 ответов
вы можете использовать команду:
grep --color='auto' -P -n "[\x80-\xFF]" file.xml
это даст вам номер строки и выделит символы, отличные от ascii, красным цветом.
в некоторых системах, в зависимости от ваших настроек, вышеуказанное не будет работать, поэтому вы можете grep обратным
grep --color='auto' -P -n "[^\x00-\x7F]" file.xml
Отметим также, что важным элементом является тег -P
флаг, который составляет --perl-regexp
: Так он будет интерпретировать ваш шаблон как регулярное выражение Perl. Он также говорит, что
это сильно экспериментальный и grep-P может предупредить о невыполнении особенности.
вместо того, чтобы делать предположения о диапазоне байтов символов, отличных от ASCII, как это делает большинство вышеприведенных решений, немного лучше IMO быть явным о фактическом диапазоне байтов символов ASCII.
таким образом, первое решение, например, станет:
grep --color='auto' -P -n '[^\x00-\x7F]' file.xml
(который в основном greps для любого символа за пределами шестнадцатеричного диапазона ASCII: от \x00 до \x7F)
на Mountain Lion, который не будет работать (из-за отсутствие поддержки PCRE в BSD grep), но с pcre
установленный через Homebrew, следующее будет работать так же хорошо:
pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml
любые плюсы или минусы, которые кто-нибудь может придумать?
для меня работает следующее:
grep -P "[\x80-\xFF]" file.xml
символы, отличные от ASCII, начинаются с 0x80 и переходят в 0xFF при просмотре байтов. Grep (и семейство) не выполняют обработку Unicode для объединения многобайтовых символов в одну сущность для сопоставления регулярных выражений, как вы, похоже, хотите. The -P
опция в моем grep позволяет использовать \xdd
escapes в классах символов, чтобы выполнить то, что вы хотите.
простой способ-определить символ, отличный от ASCII... как символ, который не является символом ASCII.
LC_ALL=C grep '[^ -~]' file.xml
Добавить вкладку после ^
при необходимости.
задание LC_COLLATE=C
избегает неприятных сюрпризов о значении диапазонов символов во многих местах. Настройка LC_CTYPE=C
необходимо соответствовать однобайтовым символам-в противном случае команда пропустит недопустимые последовательности байтов в текущей кодировке. Настройка LC_ALL=C
избегает локаль-зависимые эффекты в целом.
вот еще один вариант, который я нашел, что произвел полностью различные результаты поиска grep для [\x80-\xFF]
в принятом ответе. Возможно, кому-то будет полезно найти дополнительные символы, отличные от ascii:
grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
Примечание: grep моего компьютера (Mac) не имел -P
вариант, поэтому я сделал brew install grep
и начал вызов выше с ggrep
вместо grep
.
работает следующий код:
find /tmp | perl -ne 'print if /[^[:ascii:]]/'
заменить /tmp
С именем каталога, который вы хотите просмотреть.
странно, я должен был сделать это сегодня! Я закончил использование Perl, потому что я не мог заставить grep/egrep работать (даже в режиме-P). Что-то вроде:
cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'
для символов Unicode (например,\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 }' '{}' \;
Поиск непечатаемых символов.
Я согласен с Харви выше похоронен в комментариях, это часто более полезно для поиска непечатаемых символов или легко думать не-ASCII, когда вы действительно должны думать непечатаемых. Харви предлагает "использовать это:" [^\n -~]". Добавить \r для текстовых файлов DOS. Это переводится как "[^\x0A\x020 - \x07E] "и добавляет \x0D для CR"
кроме того, добавление -c (показать количество шаблонов matched) для grep полезен при поиске непечатаемых символов, поскольку сопоставленные строки могут испортить терминал.
я обнаружил, что добавление диапазона 0-8 и 0x0e-0x1f (в диапазон 0x80-0xff) является полезным шаблоном. Это исключает вкладку, CR и LF и один или два более необычных печатаемых символа. Так ИМХО а довольно полезный (хотя и грубый) шаблон grep-это:
grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *
поломки:
\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - perl style regexps
Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches
например. практический пример использования find to grep all files under текущий каталог:
find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} +
вы можете время от времени настраивать grep. например, BS(0x08 - backspace) char используется в некоторых файлах для печати или для исключения VT (0x0b - вертикальная вкладка). Символы BEL(0x07) и ESC(0x1B) также могут считаться печатаемыми в некоторых случаях.
Non-Printable ASCII Chars ** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes Dec Hex Ctrl Char description Dec Hex Ctrl Char description 0 00 ^@ NULL 16 10 ^P DATA LINK ESCAPE (DLE) 1 01 ^A START OF HEADING (SOH) 17 11 ^Q DEVICE CONTROL 1 (DC1) 2 02 ^B START OF TEXT (STX) 18 12 ^R DEVICE CONTROL 2 (DC2) 3 03 ^C END OF TEXT (ETX) 19 13 ^S DEVICE CONTROL 3 (DC3) 4 04 ^D END OF TRANSMISSION (EOT) 20 14 ^T DEVICE CONTROL 4 (DC4) 5 05 ^E END OF QUERY (ENQ) 21 15 ^U NEGATIVE ACKNOWLEDGEMENT (NAK) 6 06 ^F ACKNOWLEDGE (ACK) 22 16 ^V SYNCHRONIZE (SYN) 7 07 ^G BEEP (BEL) 23 17 ^W END OF TRANSMISSION BLOCK (ETB) 8 08 ^H BACKSPACE (BS)** 24 18 ^X CANCEL (CAN) 9 09 ^I HORIZONTAL TAB (HT)** 25 19 ^Y END OF MEDIUM (EM) 10 0A ^J LINE FEED (LF)** 26 1A ^Z SUBSTITUTE (SUB) 11 0B ^K VERTICAL TAB (VT)** 27 1B ^[ ESCAPE (ESC) 12 0C ^L FF (FORM FEED)** 28 1C ^\ FILE SEPARATOR (FS) RIGHT ARROW 13 0D ^M CR (CARRIAGE RETURN)** 29 1D ^] GROUP SEPARATOR (GS) LEFT ARROW 14 0E ^N SO (SHIFT OUT) 30 1E ^^ RECORD SEPARATOR (RS) UP ARROW 15 0F ^O SI (SHIFT IN) 31 1F ^_ UNIT SEPARATOR (US) DOWN ARROW
было бы интересно узнать, как искать один символ Юникода. Эта команда может помочь. Вам нужно только знать код в UTF8
grep -v $'\u200d'