Назад | Перейти на главную страницу

Как я могу использовать grep для двух значений из одного и того же ввода, переданного ему?

CentOS 5.x

Я пытаюсь создать сценарий оболочки, который ищет данные, предоставленные через стандартный ввод. Вот пример входящего потока:

Date: 1/1/11 
Time: 12:00 AM 
Foo: 12345 
Foo1: dskjflsdkjflksdjlfds 
Foo2: 123456789 
Foo3: kdsjflskdjflkjsdlkfjsdlkjflksdjflkjsdklfjlksdjflk

Эта информация не существует в файле, она будет отправлена ​​скрипту только в режиме реального времени как стандартный вывод из другого приложения.

Я хочу, чтобы сценарий просматривал данные и анализировал значения для Фу: и Foo2: сохраняя их как переменные для использования позже в скрипте.

Моя попытка пересмотренного сценария такова:

#!/bin/bash
while read data; do
        SearchCriteria1=$(echo "$data" | grep "Foo: " | cut -c 5-)
        SearchCriteria2=$(echo "$data" | grep "Foo2: " | cut -c 6-)
        echo $SearchCriteria1 >> test.1
        echo $SearchCriteria2 >> test.2
done

Готовый сценарий фактически не будет использовать файлы test.1 или test 2. Я просто перечислил их здесь для более простых примеров.

В этом примере я ожидал бы, что test.1 будет иметь:

12345

В этом примере я ожидал, что test.2 будет иметь:

123456789

Однако, когда я тестирую это, оба теста test.1 и test.2 пусты, и я знаю, что в данных есть действительная информация.

Я упускаю кое-что очевидное. Может кто-нибудь уточнить?

Подумайте, откуда ваши greps получают данные. Вы не указали им имя входного файла, поэтому они читают со стандартного ввода. Каков их стандартный ввод? Для него нет перенаправления, и нет канала, идущего в greps, поэтому они работают с унаследованным стандартным вводом цикла.

В read выполняется только один раз. Он читает первую строку в $data, который вы никогда нигде не используете (это должно быть признаком того, что что-то не так). Затем запускается первый grep, он потребляет весь ввод, а второй grep прикрепляется к тому же вводу, поэтому он немедленно получает EOF.

Вероятно, это ближе к тому, что вы хотели:

SearchCriteria1=$(echo "$data" | grep "Foo " | cut -c 10-)
SearchCriteria2=$(echo "$data" | grep "Foo2 " | cut -c 13-)

Точки с запятой в конце были бесполезны, поэтому я снял их.

Также вы, вероятно, захотите добавить в test.1 и test.2 в противном случае каждая итерация цикла перезаписывает то, что написала предыдущая.

Глядя на общую картину, кажется, что вам нужен «многопользовательский grep». Ваш цикл чтения с индивидуальными командами greps для каждой строки - это один из способов его реализации, но не очень эффективный. Некоторые другие способы недавно обсуждались на https://stackoverflow.com/questions/11676350/grepping-a-20g-file-in-bash/11676853

input stream producer |
egrep 'Foo:|Foo2:' |
while read foo data
do
        case $foo in
                Foo:) echo "do something with $foo -- $data" ;;
                Foo2:) echo "do something else with $foo -- $data" ;;
        esac
done

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

Как насчет этого:

$ ./another.app | awk '/Foo: / { print $2 }' > test.1
$ ./another.app | awk '/Foo2: / { print $2 }' > test.2