Как я grep для всех не-ASCII символов? - PullRequest
330 голосов
/ 09 июня 2010

У меня есть несколько очень больших файлов XML, и я пытаюсь найти строки, которые содержат символы не ASCII. Я пробовал следующее:

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

Но это возвращает каждую строку в файле, независимо от того, содержит ли строка символ в указанном диапазоне.

У меня неправильный синтаксис или я что-то не так делаю? Я также попробовал:

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(с одинарными и двойными кавычками вокруг шаблона).

Ответы [ 11 ]

441 голосов
/ 22 февраля 2012

Вы можете использовать команду:

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 может предупредить о невыполнении особенности.

109 голосов
/ 04 декабря 2012

Вместо того, чтобы делать предположения о диапазоне байтов не-ASCII-символов, как это делает большинство вышеупомянутых решений, немного лучше, чтобы IMO явно указывал фактический диапазон байтов символов ASCII.

Так чтоНапример, первое решение будет выглядеть следующим образом:

grep --color='auto' -P -n '[^\x00-\x7F]' file.xml

(что в основном означает grep для любого символа вне шестнадцатеричного диапазона ASCII: от \ x00 до \ x7F)

На Mountain Lion, который не будет работать (из-за отсутствия поддержки PCRE в BSD grep) , но с pcre, установленным через Homebrew, следующее также будет работать:

pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml

Есть ли плюсы или минусы, которые кто-нибудь может придумать?

66 голосов
/ 09 июня 2010

У меня работает следующее:

grep -P "[\x80-\xFF]" file.xml

Не-ASCII символы начинаются с 0x80 и переходят в 0xFF при просмотре байтов. Grep (и семейство) не выполняют обработку Unicode, чтобы объединить многобайтовые символы в одну сущность для соответствия регулярному выражению, как вам кажется. Опция -P в моем grep позволяет использовать экранирование \xdd в классах символов для достижения желаемого.

47 голосов
/ 18 октября 2011

In Perl

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile
38 голосов
/ 09 июля 2010

Самый простой способ - определить не-ASCII-символ ... как символ, не являющийся ASCII-символом.

LC_ALL=C grep '[^ -~]' file.xml

Добавить вкладку после ^, если необходимо.

Установка LC_COLLATE=C позволяет избежать неприятных сюрпризов о значении диапазонов символов во многих локалях.Установка LC_CTYPE=C необходима для соответствия однобайтовых символов, иначе команда пропустит недопустимые последовательности байтов в текущей кодировке.Установка LC_ALL=C полностью исключает зависящие от локали эффекты.

21 голосов
/ 23 марта 2016

Вот еще один вариант, который, как я обнаружил, дал полностью результатов, отличных от поиска grep для [\x80-\xFF] в принятом ответе.Возможно, кому-то будет полезно найти дополнительные не-ascii символы:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

Примечание: grep (Mac) моего компьютера не имеет опции -P, поэтому я сделалbrew install grep и начал вызов выше с ggrep вместо grep.

8 голосов
/ 14 января 2017

работает следующий код:

find /tmp | perl -ne 'print if /[^[:ascii:]]/'

Замените /tmp на имя каталога, в котором вы хотите выполнить поиск.

4 голосов
/ 21 сентября 2017

Поиск непечатаемых символов.

Я согласен с Харви выше, скрытым в комментариях, часто полезнее искать непечатные символыИЛИ легко думать не ASCII, когда вы действительно должны думать не для печати. Харви предлагает "использовать это:" [^ \ n - ~] ". Добавить \ r для текстовых файлов DOS. Это означает" [^ \ x0A \ x020- \ x07E] "и добавить \ x0D дляCR "

Кроме того, добавление -c (показать количество совпавших шаблонов) в grep полезно при поиске непечатаемых символов, так как совпавшие строки могут испортить терминал.

Я обнаружил добавление диапазона0-8 и 0x0e-0x1f (до диапазона 0x80-0xff) - полезный паттерн.Это исключает TAB, 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все файлы в текущем каталоге:

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
1 голос
/ 09 июня 2010

Странно, я должен был сделать это сегодня! Я закончил тем, что использовал 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 }' '{}' \;
0 голосов
/ 17 февраля 2019

Поиск всех символов, отличных от ascii, создает впечатление, что кто-то ищет строки в кодировке Юникод или намеревается раздеть указанные символы по отдельности.

В первом случае попробуйте один из них (переменная file используется дляавтоматизация):

 file=file.txt ; LC_ALL=C grep -Piao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[\x80-\xFF\x20]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

 file=file.txt ; pcregrep -iao '[^\x00-\x19\x21-\x7F]{7,}' $file | iconv -f $(uchardet $file) -t utf-8

Ванильный grep не работает правильно без LC_ALL = C, как отмечалось в предыдущих ответах.

Диапазон ASCII равен x00-x7F, пробел равен x20, посколькув строках есть пробелы, в которых отрицательный диапазон опускается.

Диапазон, отличный от ASCII, равен x80-xFF, так как в строках есть пробелы, в которые положительный диапазон добавляется.

Предполагается, что в строке не менее 7 последовательных символовв пределах диапазона.{7,}.

Для вывода, читаемого оболочкой, uchardet $file возвращает предположение о кодировке файла, которая передается в iconv для автоматической интерполяции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...