Как обрабатывать каждую строку, полученную в результате команды grep

У меня есть ряд строк, извлеченных из файла после запуска команды grep следующим образом:

var=`grep xyz abc.txt`

Предположим, что я получил 10 строк, которые состоят из xyz в результате.

Теперь мне нужно обработать каждую строку, полученную в результате команды grep. Как это сделать?

Ответ 1

Один из самых простых способов - не хранить вывод в переменной, а напрямую перебирать его с помощью цикла while/read.

Что-то вроде:

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

Существуют различные варианты этой схемы в зависимости от того, что вы после.

Если вам нужно изменить переменные внутри цикла (и чтобы это изменение было видно за пределами него), вы можете использовать замену процесса, как указано в answer.fonorqui:

while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)

Ответ 2

Вы можете сделать следующий цикл while read, который будет передаваться результатом команды grep, используя так называемую замену процесса:

while IFS= read -r result
do
    #whatever with value $result
done < <(grep "xyz" abc.txt)

Таким образом, вам не нужно сохранять результат в переменной, а непосредственно "вводить" его вывод в цикл.


Обратите внимание на использование IFS= и read -r в соответствии с рекомендациями в BashFAQ/001: Как я могу прочитать файл (поток данных, переменную) по очереди (и/или поле за полем)?:

Параметр -r для чтения предотвращает интерпретацию обратной косой черты (обычно используется в качестве пары новой строки обратной косой черты, чтобы продолжить несколько строк или избегать разделителей). Без этой опции любые необменимые обратные косые черты на входе будет отброшено. Вы должны почти всегда использовать -r с чтением.

В сценарии выше IFS = предотвращает обрезку ведущих и конечных пробельные. Удалите его, если вы хотите этот эффект.

Что касается замены процесса, это объясняется на странице bash хакеров:

Подстановка процесса - это форма перенаправления, где ввод или вывод процесса (некоторая последовательность команд) отображается как временная файл.

Ответ 3

Я бы предложил использовать awk вместо grep + что-то еще.

awk '$0~/xyz/{ //your code goes here}' abc.txt

Ответ 4

Без какой-либо итерации с опцией --line-buffered grep:

your_command | grep --line-buffered "your search"

Пример из реальной жизни с выходными данными команды отладки маршрутизатора Symfony PHP Framework для grep всех маршрутов, относящихся к api:

php bin/console d:r | grep --line-buffered "api"

Ответ 5

Часто порядок обработки не имеет значения. Параллельно с GNU для этой ситуации:

grep xyz abc.txt | parallel echo do stuff to {}

Если вы обрабатываете больше похоже:

grep xyz abc.txt | myprogram_reading_from_stdin

и myprogram медленнее, чем вы можете запустить:

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

Ответ 6

Переберите результаты grep с помощью цикла while/read. Как:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done