(grep) Regex для соответствия не-ASCII символам?


169

В Linux у меня есть каталог с большим количеством файлов. Некоторые из них имеют символы не ASCII, но все они действительны в формате UTF-8 . В одной программе есть ошибка, которая не позволяет ей работать с именами, отличными от ASCII, и я должен выяснить, сколько из них затронуто. Я собирался сделать это с findи затем сделать grep, чтобы напечатать символы не ASCII, и затем сделать a, wc -lчтобы найти число. Это не должно быть grep; Я могу использовать любое стандартное регулярное выражение Unix , например Perl , sed , AWK и т. Д.

Однако существует ли регулярное выражение для «любого символа, который не является символом ASCII»?


1
Пол, да, я могу использовать Perl
Рори

/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]
Тинмарино

Ответы:


310

Это будет соответствовать одному не-ASCII символу:

[^\x00-\x7F]

Это действительное PCRE ( Perl-совместимое регулярное выражение ).

Вы также можете использовать сокращения POSIX :

  • [[:ascii:]] - соответствует одному символу ASCII
  • [^[:ascii:]] - соответствует одному не-ASCII-символу

[^[:print:]] вероятно, будет достаточно для вас. **


3
@adrianm: Нет, ^действует в PCRE.
Аликс Аксель

10
Это точно верно. Однако вы должны использовать pcregrep, а не стандартный grep. [^ [: print:]] не будет работать, если ваш терминал настроен в UTF8.
Рори

@ Рори, почему :print:не работает в терминале UTF8? Это работает для меня в pry в терминале UTF8:27.chr =~ /[^[:print:]]/
akostadinov

Это очень удобно для исправления неправильных имен файлов rename 's/[^\x00-\x7F]//g' *(вы можете -nсначала проверить, что переименования в порядке).
naught101

Как мне сопоставить любой символ, отличный от UTF8, и любые другие конкретные символы?
CMCDragonkai

37

Нет, [^\x20-\x7E]это не ASCII.

Это настоящий ASCII:

 [^\x00-\x7F]

В противном случае он обрежет символы новой строки и другие специальные символы, которые являются частью таблицы ASCII!



3

[^\x00-\x7F]и [^[:ascii:]]пропустить некоторые управляющие байты, так что иногда строки могут быть лучшим вариантом. Например cat test.torrent | perl -pe 's/[^[:ascii:]]+/\n/g'будет делать странные вещи с вашим терминалом, где так же strings test.torrentбудет себя вести.




2

Вы можете использовать это регулярное выражение:

[^\w \xC0-\xFF]

Дело спрашивают, варианты Multiline .


2

Вам не нужно регулярное выражение.

printf "%s\n" *[!\ -~]*

Это также покажет имена файлов с управляющими символами в их именах, но я считаю, что это особенность.

Если у вас нет подходящих файлов, глобус расширится до самого себя, если вы не nullglobустановили. (Выражение не соответствует самому себе, так что технически этот вывод однозначен.)


Запоздал, я могу заметить , что это делает работу правильно , если вы на самом деле есть некоторые файлы , которые соответствуют этому шаблону. Поведение, при котором шаблон печатается сам, когда нет совпадений, немного удивительно, но на самом деле правильно. Я отредактировал ответ, чтобы уточнить это.
tripleee

1

Это оказалось очень гибким и расширяемым. $ field = ~ s / [^ \ x00- \ x7F] // g; # Таким образом, все не ASCII или конкретные рассматриваемые элементы могут быть очищены. Очень хорош в выборе или предварительной обработке элементов, которые в конечном итоге станут хеш-ключами.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.