У меня есть несколько очень больших файлов XML, и я пытаюсь найти строки, которые содержат символы не ASCII. Я пробовал следующее:
grep -e "[\x{00FF}-\x{FFFF}]" file.xml
Но это возвращает каждую строку в файле, независимо от того, содержит ли строка символ в указанном диапазоне.
У меня неправильный синтаксис или я делаю что-то еще неправильно? Я также попробовал:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(с одинарными и двойными кавычками вокруг шаблона).
Ответы:
Вы можете использовать команду:
Это даст вам номер строки и выделит символы не-ascii красным цветом.
В некоторых системах, в зависимости от ваших настроек, вышеприведенное не сработает, поэтому вы можете использовать grep по обратной
Также обратите внимание, что важным битом является
-P
флаг, который соответствует--perl-regexp
: поэтому он будет интерпретировать ваш шаблон как регулярное выражение Perl. Это также говорит о том, чтоисточник
grep
(на OS X 10.8 Mountain Lion), так как он не поддерживает этуP
опцию.grep
доступна вdupes
библиотеке Homebrew (включите использованиеbrew tap homebrew/dupes
):brew install grep
dupes
библиотеки является установкаpcre
вместо:brew install pcre
... как часть этого, вы получитеpcregrep
утилиту, которую вы можете использовать следующим образом:pcregrep --color='auto' -n "[\x80-\xFF]" file.xml
brew
пользователей Mac можно установить coreutils из GNUbrew install coreutils
. Это даст вам много инструментов GNU с префиксом «g» - в этом случае используйтеggrep
. Это должно избежать проблем, возникающих при замене системной утилиты, поскольку системные скрипты Mac теперь зависят от BSD grep.ag "[\x80-\xFF]" file
вам просто нужно установитьthe_silver_searcher
Вместо того, чтобы делать предположения о диапазоне байтов не-ASCII-символов, как это делает большинство вышеупомянутых решений, немного лучше, чтобы IMO явно указывал фактический диапазон байтов ASCII-символов.
Таким образом, первое решение, например, станет:
(который в основном greps для любого символа вне шестнадцатеричного диапазона ASCII: от \ x00 до \ x7F)
На Mountain Lion это не будет работать (из-за отсутствия поддержки PCRE в BSD grep) , но с
pcre
установленной через Homebrew, следующее будет работать также:Есть плюсы или минусы, которые кто-нибудь может придумать?
источник
LC_COLLATE=C grep $'[^\1-\177]'
работает (для файлов без нулевых байтов)Следующие работы для меня:
Не-ASCII символы начинаются с 0x80 и переходят в 0xFF при просмотре байтов. Grep (и семейство) не выполняют обработку Unicode, чтобы объединить многобайтовые символы в одну сущность для соответствия регулярному выражению, как вам кажется.
-P
Вариант в моем Grep позволяет использовать\xdd
побеги в классах символов , чтобы выполнить то , что вы хотите.источник
echo '소녀시대' | grep -P "[\x80-\xFF]"
для меня ничего не возвращается - кто-нибудь еще может подтвердить? (GNU grep 2.21)echo '소녀시대' | grep -P "[^\x00-\x7F]"
. Или просто используйтеthe_silver_searcher
как указано @slf:echo '소녀시대' | ag "[\x80-\xFF]"
В перл
источник
perl -lne 'print if /[^[:ascii:]]/' file.xml
Самый простой способ - определить не-ASCII-символ ... как символ, не являющийся ASCII-символом.
Добавьте вкладку после
^
если это необходимо.Параметр
LC_COLLATE=C
позволяет избежать неприятных сюрпризов о значении диапазонов символов во многих локалях. УстановкаLC_CTYPE=C
необходима для соответствия однобайтовых символов - в противном случае команда пропустит недопустимые последовательности байтов в текущей кодировке. Настройка полностьюLC_ALL=C
исключает зависящие от локали эффекты.источник
echo "A" | LC_COLLATE=C grep '[^ -~]'
возвращается матчLC_ALL=en_US.UTF-8
, это превосходитLC_COLLATE
настройки. Вы не должны иметь это в своей среде!LC_ALL
обычно заставляет определенную задачу использовать конкретную локальC
. Чтобы установить язык по умолчанию для всех категорий, установитеLANG
.LC_ALL=C
, это ведет себя по-разному в Mac OS X и Ubuntu. После того, как я добавлю этот параметр, они дают тот же результат.Вот еще один вариант, который я обнаружил, который дал совершенно разные результаты поиска grep
[\x80-\xFF]
в принятом ответе. Возможно, кому-то будет полезно найти дополнительные символы, не относящиеся к ascii:grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
Примечание: у grep моего компьютера (Mac) не было
-P
опции, поэтому я сделалbrew install grep
и начал вызов выше сggrep
вместоgrep
.источник
Следующий код работает:
Замените
/tmp
на имя каталога, который вы хотите найти.источник
Поиск непечатаемых символов. TLDR; Управляющее резюме
LC_ALL=C
необходимая, чтобы grep делал то, что вы могли ожидать с расширенным юникодомТак что предпочтительные не ASCII Char Finders:
как в верхнем ответе, обратный grep:
как в верхнем ответе, но с
LC_ALL=C
:, , Больше . , Мучительная деталь в этом: , ,
Я согласен с Харви выше, погруженным в комментарии, часто полезнее искать непечатные символы ИЛИ легко думать не ASCII, когда вы действительно должны думать, что вы не печатаете. Харви предлагает "использовать это:"
[^\n -~]
". Добавьте \ r для текстовых файлов DOS. Это означает"[^\x0A\x020-\x07E]
"и добавьте \ x0D для CR"Кроме того, добавление -c (показать количество совпавших шаблонов) в grep полезно при поиске непечатаемых символов, поскольку соответствующие строки могут испортить терминал.
Я обнаружил, что добавление диапазона 0-8 и 0x0e-0x1f (к диапазону 0x80-0xff) является полезным шаблоном. Это исключает TAB, CR и LF и один или два необычных печатных символа. ИМХО, довольно полезный (хотя и грубый) шаблон grep это:
В действительности, как правило, вам нужно сделать это:
сломать:
Например, практический пример использования find для поиска всех файлов в текущем каталоге:
Вы можете настроить grep время от времени. например, BS (0x08 - backspace) char, используемый в некоторых печатаемых файлах или для исключения VT (0x0B - вертикальная вкладка). Символы BEL (0x07) и ESC (0x1B) также могут считаться пригодными для печати в некоторых случаях.
ОБНОВЛЕНИЕ: я должен был вернуться к этому недавно. И, YYMV в зависимости от настроек терминала / прогноза солнечной погоды, НО. , Я заметил, что grep не находил много юникодов или расширенных символов. Хотя интуитивно они должны соответствовать диапазону от 0x80 до 0xff, 3 и 4-байтовые символы Unicode не были сопоставлены. ??? Кто-нибудь может объяснить это? ДА. @frabjous спросил и @calandoa объяснил, что
LC_ALL=C
следует использовать, чтобы установить языковой стандарт для команды, чтобы сделать совпадение grep.например, мой язык
LC_ALL=
пустgrep с
LC_ALL=
пустыми совпадениями 2-байтовые кодированные символы, но не 3 и 4-байтовые:grep с
LC_ALL=C
действительно соответствует всем расширенным символам, которые вы хотели бы:НАСТОЯЩЕЕ соответствие perl (частично найденное в другом месте в stackoverflow) ИЛИ обратный grep в верхнем ответе, похоже, обнаруживает ВСЕ странные ~ и ~ чудесные ~ "не-ascii" символы без установки языкового стандарта:
Так что предпочтительные не ASCII Char Finders:
как в верхнем ответе, обратный grep:
как в верхнем ответе, но с
LC_ALL=C
:источник
Странно, я должен был сделать это сегодня! Я закончил тем, что использовал Perl, потому что я не мог заставить работать grep / egrep (даже в режиме -P). Что-то вроде:
Для символов Юникода (например,
\u2212
в примере ниже) используйте это:источник
Было бы интересно узнать, как искать один символ Юникода. Эта команда может помочь. Вам нужно только знать код в UTF8
источник
Поиск всех символов, отличных от ascii, создает впечатление, что кто-то ищет строки в юникоде или намеревается раздеть эти символы по отдельности.
Для первого, попробуйте один из них (переменная
file
используется для автоматизации):Ванильный grep не работает правильно без LC_ALL = C, как отмечалось в предыдущих ответах.
Диапазон ASCII есть
x00-x7F
, пространствоx20
, так как в строках есть пробелы, которые отрицательный диапазон пропускает.Диапазон не ASCII
x80-xFF
, так как строки имеют пробелы, положительный диапазон добавляет его.Предполагается, что строка должна содержать не менее 7 последовательных символов в диапазоне.
{7,}
,Для вывода, читаемого оболочкой,
uchardet $file
возвращает предположение о кодировке файла, которая передается в iconv для автоматической интерполяции.источник
uchardet
команды. Спасибо за это хедз-ап!