Как безопасно использовать вывод grep в скрипте?

В сценарии я хочу найти файлы, содержащие некоторый текст. Мне нужно знать файл, в котором находится текст, и полную строку в файле, в которой находится текст. grep – это утилита, которая делает это, но как я могу получить вывод в полезную форму, учитывая, что быть : в именах файлов? Есть ли какой-то --porcelain режим для grep который я могу использовать, вроде как команды git часто имеют?

Пример. У меня есть папка с файлами с именем test-num:1:date:jan-2 которую я хочу пропустить. Файлы содержат FAILURE:<some reason> или SUCCESS:<some reason> (среди прочего). Мне нужен сценарий, который ищет определенные причины и сохраняет имя файла, и причина (вся строка текста в порядке) для последующей обработки. Вывод может быть в любом виде структуры данных, если я могу запустить над ним код.

3 Solutions collect form web for “Как безопасно использовать вывод grep в скрипте?”

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

 pattern='some pattern' for file in ./*; do grep -- "$pattern" "$file" | while read -r line; do printf 'file: %s, line: %s\n' "$file" "$line" done done 

В последних (-ish) версиях GNU grep есть опция -Z которая делает вывод однозначным, но в основном он предназначен для использования как grep -lZ … | xargs -0 grep -lZ … | xargs -0 . Он по-прежнему работает, если вы перечисляете содержимое строки, нулевой байт заменяет двоеточие, а содержимое линии все еще заканчивается на новой строке¹, но оболочки не подходят для обработки нулевых байтов, поэтому вам будет трудно разобрать этот вывод ,

Одним простым решением (с небольшим снижением производительности) является запуск grep для каждого файла по отдельности.

Другое решение – использовать язык Perl или Python. Perl очень хорош в эмуляции grep; grep REGEX в основном perl -ne '/REGEXP/ and print' .

Но вам может не понадобиться это вообще, если вывод не является фактически двусмысленным. Например, если совпадающие строки не содержат двоеточие, тогда имя файла – это все в строке до последнего двоеточия. Если соответствующие строки начинаются с SUCCESS или FAILURE и эти слова не отображаются в именах файлов, вы можете использовать это, чтобы найти разделение и т. Д.

¹ За исключением случаев использования -z для фильтрации записей с нулевым завершением, а не для записей с завершающим расширением строки, то null – это как ограничитель имени файла, так и терминатор результата; без -o выход по-прежнему однозначен, причем переменные выходные записи являются именами файлов и соответствующими записями на выходе.

Как безопасно использовать вывод grep в скрипте?

… Выход может быть в любом виде структуры данных, пока я могу запускать над ним код.

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

Лучший способ запустить код над вашими файлами в сценарии оболочки – просто запустить код поверх файлов, а не пытаться сохранить имена файлов для последующего использования.

Для этого используйте find :

 find somedir -type f -exec grep -q somepattern {} \; -exec somecommand {} \; 

Однако, читая ваш вопрос более внимательно, похоже, что вы на самом деле не хотите запускать код поверх своих файлов, вы просто хотите сделать некоторую текстовую обработку на определенных строках. В этом случае опция -z Grep -z – это, вероятно, то, что вы хотите. Это, и знание Sed или Awk, будет решать ваш вопрос.


Возможно, было бы разумно изменить соглашение об именах файлов.

  • Фильтровать имена из текстового файла
  • Извлечение столбцов строки с помощью grep
  • ps | grep показывает плохой результат в подоболочке с заданиями, работающими в фоновом режиме
  • Удалить строки из файла, который существует в другом файле с более новой меткой времени
  • Строки, заключенные в '', игнорируются при использовании grep
  • Список файлов, содержащих меньше N строк, соответствующих шаблону / строке
  • grep: отображать имя файла один раз, затем отображать контекст с номерами строк
  • Как извлечь число из строки ниже, которая является выводом команды?
  • grep фиксированная строка в конце строки
  • Получение только определенных данных на основе имени в текстовом файле
  • Как использовать не жадное регулярное выражение в grep?
  • Linux и Unix - лучшая ОС в мире.