Как искать строки в файле, которые содержат только символы ASCII, а затем действовать на них?

Чтобы найти файлы (совместимые с файлами, включая пробел / или новую строку), они не содержат шаблон address:

find -type f ! -exec grep -q 'address' {} \; -print 

и печатают только те, которые содержат шаблоны fax и [ f7] в любом порядке всего файла:

find -type f ! -exec grep -q 'address' {} \; \
               -exec grep -qP '(?s)(?=.*?fax)(?=.*?phone)' {} \; -print

Или POSIXly:

find -type f ! -exec grep -q 'address' {} \; \
               -exec grep -q 'fax' {} \; \
               -exec grep -q 'phone' {} \; -print

Или если в имени файлов нет \n ewline, тогда: [!d5 ]

grep -lP '(?s)(?=.*?fax)(?=.*?phone)' * |xargs -d'\n' grep -L address
(?=pattern): Положительный Lookahead: Положительная конструкция lookahead представляет собой пару круглых скобок, с открывающейся скобкой, за которой следует знак вопроса и знак равенства. (?s) Известная «точка-все», которая сообщает grep, чтобы точка . соответствовала символам \n. [F13] означает сопоставление любых символов ., которые появляются ноль или более раз *, в то время как они являются необязательными, а затем шаблон (fax или phone). [F18] делает все необязательным перед ним (означает нуль или одно время всего, что соответствует .*) будущее чтение:

Regex lookahead, lookbehind и атомные группы

6
задан 26 April 2018 в 19:54

6 ответов

Кажется, вы можете использовать sed для выполнения этой задачи, даже если он не знает о классе символов [[:ascii:]]. Вместо этого мы можем указать все символы ASCII с рядом escape-последовательностей [\d0-\d127], если мы используем локали C или POSIX.

Вот команда, которая должна быть надежной:

LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file

Примечания

LC_ALL=C Используйте C настройки локали только для этой команды (иначе вы получите сообщение об ошибке) -r Используйте расширенное регулярное выражение, чтобы сделать команду более читаемой (нам нужно меньше обратных косых черт) (GNU sed также распознает -E с тем же значением). :a Здесь начинается цикл меток ; Разделяет команды, как в оболочке N. Прочитайте следующую строку в пространстве шаблонов, поэтому мы можем заменить \n s|old|new| Заменить old на new - сопоставить две строки только с ASCII и захватить первую строку в \1 и вторую строку в \2. ^ - начало строки, \n - новая строка, а $ - конец строки, поэтому ^line 1\nline 2$ проверяет все line 1 и line 2. \1 / \2 Первая и вторая строки, разделенные  /  вместо новой строки. ta - Если последняя команда поиска и замены выполнена успешно, повторите цикл. Это позволяет нам обрабатывать все строки файла, обрабатывая все экземпляры, в которых имеется более двух строк ASCII.

Большое спасибо Eliah Kagan за то, что он показал мне, как использовать escape-последовательности для соответствия символам ASCII.

4
ответ дан 22 May 2018 в 11:14
  • 1
    Спасибо за эту команду, это сработало как прелесть. В качестве дополнительной заметки для новичков, таких как я, нужно добавить > outputfile.txt в конце команды (после того, как в команде указано выше file, которая является входным файлом), чтобы результаты фактически сохранялись в файл. – Questioner 27 April 2018 в 03:38

Кажется, вы можете использовать sed для выполнения этой задачи, даже если он не знает о классе символов [[:ascii:]]. Вместо этого мы можем указать все символы ASCII с рядом escape-последовательностей [\d0-\d127], если мы используем локали C или POSIX.

Вот команда, которая должна быть надежной:

LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file

Примечания

LC_ALL=C Используйте C настройки локали только для этой команды (иначе вы получите сообщение об ошибке) -r Используйте расширенное регулярное выражение, чтобы сделать команду более читаемой (нам нужно меньше обратных косых черт) (GNU sed также распознает -E с тем же значением). :a Здесь начинается цикл меток ; Разделяет команды, как в оболочке N. Прочитайте следующую строку в пространстве шаблонов, поэтому мы можем заменить \n s|old|new| Заменить old на new ^([\d0-\d127])\n([\d0-\d127]+)$ - сопоставить две строки только с ASCII и захватить первую строку в \1 и вторую строку в \2. ^ - начало строки, \n - новая строка, а $ - конец строки, поэтому ^line 1\nline 2$ проверяет все line 1 и line 2. \1 / \2 Первая и вторая строки, разделенные  /  вместо новой строки. ta - Если последняя команда поиска и замены выполнена успешно, повторите цикл. Это позволяет нам обрабатывать все строки файла, обрабатывая все экземпляры, в которых имеется более двух строк ASCII.

Большое спасибо Eliah Kagan за то, что он показал мне, как использовать escape-последовательности для соответствия символам ASCII.

4
ответ дан 17 July 2018 в 16:07

Кажется, вы можете использовать sed для выполнения этой задачи, даже если он не знает о классе символов [[:ascii:]]. Вместо этого мы можем указать все символы ASCII с рядом escape-последовательностей [\d0-\d127], если мы используем локали C или POSIX.

Вот команда, которая должна быть надежной:

LC_ALL=C sed -r ':a;N;s|^([\d0-\d127]+)\n([\d0-\d127]+)$|\1 / \2|;ta' file

Примечания

LC_ALL=C Используйте C настройки локали только для этой команды (иначе вы получите сообщение об ошибке) -r Используйте расширенное регулярное выражение, чтобы сделать команду более читаемой (нам нужно меньше обратных косых черт) (GNU sed также распознает -E с тем же значением). :a Здесь начинается цикл меток ; Разделяет команды, как в оболочке N. Прочитайте следующую строку в пространстве шаблонов, поэтому мы можем заменить \n s|old|new| Заменить old на new ^([\d0-\d127])\n([\d0-\d127]+)$ - сопоставить две строки только с ASCII и захватить первую строку в \1 и вторую строку в \2. ^ - начало строки, \n - новая строка, а $ - конец строки, поэтому ^line 1\nline 2$ проверяет все line 1 и line 2. \1 / \2 Первая и вторая строки, разделенные  /  вместо новой строки. ta - Если последняя команда поиска и замены выполнена успешно, повторите цикл. Это позволяет нам обрабатывать все строки файла, обрабатывая все экземпляры, в которых имеется более двух строк ASCII.

Большое спасибо Eliah Kagan за то, что он показал мне, как использовать escape-последовательности для соответствия символам ASCII.

4
ответ дан 23 July 2018 в 17:01

Если вы хотите, чтобы целые строки состояли только из символов ASCII, вам необходимо привязать ваш шаблон к началу и концу строки, например. с grep

$ grep -P '^[[:ascii:]]*$' file
English words only
English words only
English words only
Also English words only
English words only

Некоторые инструменты предоставляют флаг целой строки, такой как grep's -x или --line-regexp:

   -x, --line-regexp
          Select  only  those  matches  that exactly match the whole line.
          For a regular expression pattern, this  is  like  parenthesizing
          the pattern and then surrounding it with ^ and $.

позволяя вам использовать:

$ grep -Px '[[:ascii:]]*' file
English words only
English words only
English words only
Also English words only
English words only

сопоставление целых строк добавляет целый другой уровень сложности, поскольку многие общие утилиты обработки текстовой информации командной строки основаны на линиях. Вы можете заставить grep обрезать целый файл с помощью флага -Z, однако в этом случае, вероятно, более подходящими являются такие инструменты, как pcregrep или perl.

Следующий вопрос, который вам нужно решить, - это интерпретировать понятия «начало строки» и «конец строки» в контексте многострочного совпадения. Некоторые инструменты предоставляют для этого флаги, как описано в учебнике по регулярному выражению: Anchors: perl является одним из них, который предоставляет модификатор /m. Вам по-прежнему необходимо развернуть файл, отменив разделитель записей по умолчанию (здесь делается -0777); например

$ perl -0777 -pe 's{^([[:ascii:]]+)\n([[:ascii:]]+)$}{$1 / $2}mg' file
English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
English words only / Also English words only
English and 日本語
日本語のみ
English words only
English and 日本語
日本語のみ
4
ответ дан 22 May 2018 в 11:14

Если вы хотите, чтобы целые строки состояли только из символов ASCII, вам необходимо привязать ваш шаблон к началу и концу строки, например. с grep

$ grep -P '^[[:ascii:]]*$' file English words only English words only English words only Also English words only English words only

Некоторые инструменты предоставляют флаг целой строки, такой как grep's -x или --line-regexp:

-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.

позволяя вам использовать:

$ grep -Px '[[:ascii:]]*' file English words only English words only English words only Also English words only English words only

сопоставление целых строк добавляет целый другой уровень сложности, поскольку многие общие утилиты обработки текстовой информации командной строки основаны на линиях. Вы можете заставить grep обрезать целый файл с помощью флага -Z, однако в этом случае, вероятно, более подходящими являются такие инструменты, как pcregrep или perl.

Следующий вопрос, который вам нужно решить, - это интерпретировать понятия «начало строки» и «конец строки» в контексте многострочного совпадения. Некоторые инструменты предоставляют для этого флаги, как описано в учебнике по регулярному выражению: Anchors: perl является одним из них, который предоставляет модификатор /m. Вам по-прежнему необходимо развернуть файл, отменив разделитель записей по умолчанию (здесь делается -0777); например

$ perl -0777 -pe 's{^([[:ascii:]]+)\n([[:ascii:]]+)$}{$1 / $2}mg' file English words only English and 日本語 日本語のみ English words only English and 日本語 日本語のみ English words only / Also English words only English and 日本語 日本語のみ English words only English and 日本語 日本語のみ
4
ответ дан 17 July 2018 в 16:07

Если вы хотите, чтобы целые строки состояли только из символов ASCII, вам необходимо привязать ваш шаблон к началу и концу строки, например. с grep

$ grep -P '^[[:ascii:]]*$' file English words only English words only English words only Also English words only English words only

Некоторые инструменты предоставляют флаг целой строки, такой как grep's -x или --line-regexp:

-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.

позволяя вам использовать:

$ grep -Px '[[:ascii:]]*' file English words only English words only English words only Also English words only English words only

сопоставление целых строк добавляет целый другой уровень сложности, поскольку многие общие утилиты обработки текстовой информации командной строки основаны на линиях. Вы можете заставить grep обрезать целый файл с помощью флага -Z, однако в этом случае, вероятно, более подходящими являются такие инструменты, как pcregrep или perl.

Следующий вопрос, который вам нужно решить, - это интерпретировать понятия «начало строки» и «конец строки» в контексте многострочного совпадения. Некоторые инструменты предоставляют для этого флаги, как описано в учебнике по регулярному выражению: Anchors: perl является одним из них, который предоставляет модификатор /m. Вам по-прежнему необходимо развернуть файл, отменив разделитель записей по умолчанию (здесь делается -0777); например

$ perl -0777 -pe 's{^([[:ascii:]]+)\n([[:ascii:]]+)$}{$1 / $2}mg' file English words only English and 日本語 日本語のみ English words only English and 日本語 日本語のみ English words only / Also English words only English and 日本語 日本語のみ English words only English and 日本語 日本語のみ
4
ответ дан 23 July 2018 в 17:01

Другие вопросы по тегам:

Похожие вопросы: