2015-04-30 4 views
-1

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

  1. поиска первого вхождения RequestString
  2. экстракта PID из этой строки журнала
  3. поиска в обратном направлении для первого вхождения PID<separator>ConnectionString, чтобы идентифицировать клиент, который инициировал запрос
  4. сделать что-то с ConnectionString и повторить поиск с после того, как «» RequestString

Каков наилучший способ сделать это? Я подумывал написать сценарий perl, чтобы сделать это с помощью кэширования последних строк N, а затем выполнить соответствующие линии для выполнения 3.

Есть ли лучший способ сделать это? Как расширенное регулярное выражение, которое будет делать именно это?

Образец с номерами строк для справки - не часть файла:

1 date pid1 ConnectionString1 
2 date pid2 ConnectionString2 
3 date pid3 ConnectionString3 
4 date pid2 SomeOutput2 
5 date pid2 SomeOutput2 
6 date pid4 ConnectionString4 
7 date pid3 SomeOutput3 
8 date pid4 RequestString4 
9 date pid1 SomeOutput1 
10 date pid1 ConnectionString1 
11 date pid1 RequestString1 
12 date pid5 RequestString5 

Когда я Grep через этот файл образца, я хотел бы для следующего, чтобы соответствовать:

  • линии 8, в паре с линией 6
  • линии 11, в паре с линией 10 (а не с линии 1)

Sp ecifically, следующие не должны быть согласованы:

  • строка 12, потому что нет соответствия ConnectionString с этим PID не найден (pid5)
  • линия 1, потому что это новый ConnectionString для этого PID до следующего RequestString для этого pid (строка 10). Представьте себе, что первая попытка подключения завершилась неудачно, прежде чем регистрировать RequestString)
  • любая из строк из pid2/pid3, потому что он не имеет регистрацию RequestString.

Возможно, я мог бы написать регулярное выражение с опцией. для соответствия \ n: ((pid\d)\s*(ConnectionString\d))(?!\1).*\2\s*RequestString\d, а затем используйте \3 для идентификации клиента.

Однако, есть непропорционально больше (возможно, от 1000 до 10000 раз больше) ConnectionString s, чем RequestString с, так что моя интуиция была первым идти на RequestString, а затем вернуться назад.

Я думаю, что я мог бы играть с (? <) для lookbehind, но длины между ConnectionString и RequestString s по существу произвольны - это будет хорошо работать?

+0

Пожалуйста, покажите пример файла. –

ответ

1

Что-то вдоль этих линий:

#!/bin/bash 
# Find and number all RequestStrings, then loop through them 
grep -n RequestString file | while IFS=":" read n string; do 
    echo $n,$string # Debug 
    head -n $n file | tail -r | grep -m1 Connection 
done 

Выход

4,RequestString 1 
6189:Connection 
7,RequestString 2 
7230:Connection 
9,RequestString 3 
8280:Connection 

с этим входным файлом

6189:Connection 

RequestString 1 
7229:Connection 
7230:Connection 
RequestString 2 
8280:Connection 
RequestString 3 

Примечание: я использовал tail -r потому OSX не хватает tac, который я бы предпочел.

+0

'RequestString' содержит pid, который используется для соответствия последней строке Connection до строки запроса. – Irfy

+1

Это будет моя переменная, называемая 'string', поэтому вы можете легко ее проанализировать - либо в исходном' grep', используя опцию '-o', либо в цикле, используя подстановку параметров bash ... http: // www.tldp.org/LDP/abs/html/parameter-substitution.html –

+0

Я собираюсь попробовать регулярное выражение lookbehind, чтобы сделать это, это причина задержки. Думаю, я мог бы принять ваш ответ до тех пор и пересмотреть лучшее решение, когда у меня есть что-то. – Irfy