2010-06-08 2 views
264

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

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

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

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

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

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

+0

Символы ASCII имеют длину только один байт, поэтому, если файл не является unicode, не должно быть символов выше 0xFF. – zdav

+0

Как мы переходим к \ xFF? Grep дает ошибку «grep: range out of order in character class». –

ответ

372

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

grep --color='auto' -P -n "[\x80-\xFF]" file.xml 

Это даст вам номер строки и выделить не-ASCII символы в красном цвете.

В некоторых системах, в зависимости от ваших настроек, выше не будет работать, так что вы можете вычленить инверсией

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

Следует также отметить, что важным бит является -P флаг, который приравнивает к --perl-regexp: так он будет интерпретировать ваш шаблон как регулярное выражение Perl.Он также говорит, что

this is highly experimental and grep -P may warn of unimplemented features.

+33

Это не будет работать в BSD' grep' (on OS X 10.8 Mountain Lion), поскольку он не поддерживает опцию 'P'. –

+20

Чтобы обновить мой последний комментарий, версия GNU 'grep' доступна в библиотеке' dupes' в Homebrew (включите использование 'brew tap homebrew/dupes'):' brew install grep' –

+41

@BastiaanVanDeWeerd верен, grep на OSX 10.8 нет более длинная поддержка PCRE («Perl-совместимые регулярные выражения»), поскольку Darwin теперь использует BSD grep вместо GNU grep. Альтернативой установке библиотеки 'dupes' является установка' pcre' вместо: 'brew install pcre' ... как часть этого, вы получите утилиту' pcregrep', которую вы можете использовать следующим образом: 'pcregrep - color = 'auto' -n "[\ x80- \ xFF]" file.xml' – pvandenberk

1

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

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

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

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

+1

Для представления, которое может не сразу узнать, как вызвать это по нескольким файлам, просто запустите: find. -name * .xml | xargs grep -P "[\ x80- \ xFF]" –

+1

Это возвращает совпадение, но нет указания того, что такое символ и где он находится. Как вы видите, что такое персонаж, и где оно? –

+0

Добавление «-n» даст номер строки, дополнительно невидимые символы будут отображаться как блок на терминале: grep -n -P "[\ x80- \ xFF]" file.xml – fooMonster

30

Простым способом является определение символа не ASCII ... как символ, который не является символом ASCII.

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

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

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

+0

На RedHat 6.4 с tcsh мне пришлось использовать <<< env LC_COLLATE = C grep -n '[^ - ~]' file.xml >>>. Я добавил -n, чтобы получить номер строки. – ddevienne

+0

Для меня 'echo" A "| LC_COLLATE = C grep '[^ - ~]' 'возвращает соответствие – frabjous

+0

@frabjous Этого не должно быть. Каковы ваши другие настройки языка (вывод «locale')? На какой платформе? – Gilles

43

В Perl'х

perl -ane '{ if(m/[[:^ascii:]]/) { print } }' fileName > newFile 
+0

Около -1 для бесполезного использования кошки. См. Http://patrmaps.org/era/unix/award.html – tripleee

+0

Я согласен с @tripleee. Вы можете отредактировать свой ответ. –

+9

Я нашел, что это работает лучше для меня на OSX – ryanneufeld

90

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

Таким образом, первое решение, например, стал бы:

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

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

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

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

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

+8

Это действительно сработало для меня, когда вышеприведенные решения не удались. Найти апострофы M $ Word было не так просто! –

+1

Если у вас есть совместимая с bash оболочка, но не pcre-grep, то работает 'LC_COLLATE = C grep $ '[^ \ 1- \ 177]'' (для файлов без пустых байтов) – idupree

+2

Это решение работает более последовательно, чем выше. – 0xcaff

13

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

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

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

0

Может быть интересно узнать, как искать один символ Юникода. Эта команда может помочь. Вам нужно только знать код в UTF8

grep -v $'\u200d' 
4

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

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

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

+0

На Mac это работает, в то время как большинство из grep-based нет. –

0

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

Я согласен с Harvey выше, погребенный в комментариях, часто более полезно искать непечатаемые символы или легко думать о не-ASCII, когда вы действительно должны думать о непечатаемой. Harvey предлагает «использовать это:« [^ \ 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 

Е.Г. практический пример использования найти в 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 
Смежные вопросы