Этот вопрос представляет собой вариант Как мне grep для нескольких шаблонов на нескольких строках?
Это пример текста, в котором строки, содержащие «reqId: regexpat» или «reqCompleted: regexpat», должны быть сопоставлены в пары, где 'regexpat' уникален, на самом деле это может быть UUID.
2016-09-27 GET /some/uri - reqId: 000-pat1-bgr, more text
2016-09-27 GET /some/uri - reqId: 0.215487, your favourite song
2016-09-27 irrelevant message
2016-09-27 ignored record
2016-09-27 reqCompleted: 999-xxx-vvv, ignore this
2016-09-27 reqCompleted: 0.215487, more characters
2016-09-27 reqCompleted: 000-pat1-bgr, more characters
2016-09-27 another lost message
Ожидаемый результат должен быть
2016-09-27 GET /some/uri - reqId: 000-pat1-bgr, more text
2016-09-27 GET /some/uri - reqId: 0.215487, your favourite song
2016-09-27 reqCompleted: 0.215487, more characters
2016-09-27 reqCompleted: 000-pat1-bgr, more characters
000-pat1-bgr и 0.215487 являются уникальными идентификаторы. Я пробовал grep с поддержкой perl-regex
grep --null-data --only-matching --perl-regex '(?s)^\N+ RequestId:\1, \N+$\n(?:.*)^\N+ reqCompleted: ([a-z0-9\.-]+), .\N+$\n'
Но это то, что я получаю
2016-09-27 GET /some/uri - reqId: 000-pat1-bgr, more text
2016-09-27 GET /some/uri - reqId: 0.215487, your favourite song
2016-09-27 irrelevant message
2016-09-27 ignored record
2016-09-27 reqCompleted: 999-xxx-vvv, ignore this
2016-09-27 reqCompleted: 0.215487, more characters
2016-09-27 reqCompleted: 000-pat1-bgr, more characters
Можно ли добиться этого с помощью команды liner grep?
Используя awk, найденное решение:
awk 'BEGIN{FS=":|,";i=0;}
/reqCompleted/ || /reqId/{
arr[$i]=$2;
lines[$i]=$0;
i++;
}END{
for(key in arr){
if(arr[key] in arr){
}else{
print lines[key]
};
}
}' input.txt
Это дает ожидаемый результат как:
2016-09-27 reqCompleted: 000-pat1-bgr, more characters
2016-09-27 GET /some/uri - reqId: 0.215487, your favourite song
2016-09-27 reqCompleted: 0.215487, more characters
2016-09-27 GET /some/uri - reqId: 000-pat1-bgr, more text