Начиная с версии 2.25, фиксируется "bug" in grep, так что для завершения выходных строк используются нулевые байты, а не символы новой строки. Это работает так хорошо, как просто для захвата и обработки многострочных grep-матчей (см. Пример)Как обрабатывать каждый результат - вместо строки команды grep (oz) (старше 2.25)
К сожалению, я придерживаюсь версии grep версии 2.20 на производстве. Это означает, что для обработки \ n завершенных лог-файлов вы не можете отличить grep-match от каждой отдельной строки вывода.
Поэтому мой вопрос:
Что является наиболее эффективным способом для обработки каждого результата -instead из line- команды Grep (OZ), когда вы застряли с версии старше 2.25?
(Примечание: это небольшой пример более сложного сценария, который необходимо обработать более после 10k больших логах по запросу, поэтому мои поиски «наиболее эффективным» решением)
Простой пример:
test.log
flag test1
flag test2
flag test3
test4
test5
flag test6
test7
flag test8
test.sh
#!/bin/bash
#regex explained:
#(?s)enable multiline pattern search
#(flag) capturegroup with pattern indicating new entry
#[[:blank:]] followed by a space
#(.*?) capturegroup for the rest of the entry, non-greedy
#(?=(?:\r\n|[\r\n])(flag)|\z) positive lookahead:
# - stop when the next newline begins with flag
# - OR if last entry is a match: proceed 'till end of entry
regex_multiline="(?s)(flag)[[:blank:]](.*?)(?=(?:\r\n|[\r\n])(flag)|\z)"
logfile="./test.log"
test1(){
#this works only with grep 2.25 or higher,
#which returns a NULL-byte delimiter after each capture
echo start
while IFS= read -r -d '' line ; do
printf '<test>%s</test>\n' "$line"
done < <(grep -Pzo $regex_multiline $logfile)
echo end
}
test2(){
#I need this to work for each match, instead of each line
echo start
while IFS= read -r line ; do
printf '<test>%s</test>\n' "$line"
done < <(grep -Pzo $regex_multiline $logfile)
echo end
}
Test 1 приводит, что я хочу:
start
<test>flag test1</test>
<test>flag test2</test>
<test>flag test3
test4
test5</test>
<test>flag test6
test7
</test>
<test>flag test8</test>
end
Тест 2 Результаты в
start
<test>flag test1</test>
<test>flag test2</test>
<test>flag test3</test>
<test> test4</test>
<test> test5</test>
<test>flag test6</test>
<test></test>
<test>test7</test>
<test> </test>
<test>flag test8</test>
end
Test 2 терпит неудачу, потому что вы удалили нулевой ограничитель '-d ''' в 'read', но' grep' продолжает производить вывод, 'NULL' разделил – Inian
Нет, тест 2 не с' -d '' ', потому что grep pre 2.25 делает * not * производят null-output, но \ n вместо этого. (как указано в ссылке в моем OP). Если вы попробуете Test1 с grep <2.25, вы просто получите 'start \ nend' – Asgair
Вам разрешено использовать другие инструменты, или это нужно сделать с помощью grep? –