이것은 stackoverflow에 내 첫 게시물입니다. \ 0/ 항목이 너무 길지 않기를 바랍니다. 저는 수천 개의 로그 파일에서 정기적으로 데이터를 읽고 필터링하고 출력하는 BASH 스크립트를 작성하고 있습니다. 성능이 중요합니다. 그래서 내가 주로 awk 나 sed 대신에 grep을 사용하고 있습니다.Bash 어떻게 효율적으로 grep을 조작 할 수 있습니까? -Pold multiline output?
grep -Poz는 추가 처리와 관련된 패턴을 사용하여 (다중 행) 데이터를 캡처하는 것과 똑같지 만, 예를 들어 XML 파일이나 SQLite3 일괄 처리 데이터와 같은 데이터를 조작하는 데 주저합니다. 추가 분석을위한 쿼리.
#!/bin/bash
# Regex:
# (?s) multiline search
# Capturegroup 1 = date
# Capturegroup 2 = time
# Capturegroup 3 = error type (ERROR, WARN or DEBUG)
# Capturegroup 4 = error details
# Positive lookahed, until new line (windows/linux) starts with date, OR (if it's the last line matching the pattern, till the end of the last line.
#
REGEX_MULTILINE="(?s)([0-9]{4}-[0-9]{2}-[0-9]{2})[[:space:]]([0-9]{2}:[0-9]{2}:[0-9]{2}[,|.][0-9]{3})[[:space:]]+(ERROR|WARN|DEBUG)(.*?)(?=(?:\r\n|[\r\n])[0-9]{4}-[0-9]{2}-[0-9]{2}|\z)"
LOGFILE="test.log"
# write to logfile gives exactly the info I want
write_log(){
echo -n $(grep -Pzo $REGEX_MULTILINE $LOGFILE) > output_grep1.txt
}
# I'm stuck in this part to generate, for example, an XML-file
write_xml(){
local LOGDATE=""
local LOGTIME=""
local LOGTYPE=""
local LOGINFO=""
while IFS= read -r LINE ; do
#For testing purposes, to see if brackets contain the full string,
#or a line of that string
printf '%s\n' "[$LINE]"
#processing logic here. Didn't get this far yet
while [[ $LINE =~ $REGEX_MULTILINE ]] ; do
# regex capturegoups
LOGDATE=${BASH_REMATCH[1]}
LOGTIME=${BASH_REMATCH[2]}
LOGTYPE=${BASH_REMATCH[3]}
LOGINFO=${BASH_REMATCH[4]}
# send vars to function for output
# write_xml_function $LOGDATE $LOGTIME $LOGTYPE $LOGINFO
# for testing purposes
echo -e "log entry:\n\t 1: $LOGDATE \n\t 2: $LOGTIME \n\t 3: $LOGTYPE \n\t 4: $LOGINFO \n"
break
done
done < <(grep -Pzo $REGEX_MULTILINE $LOGFILE)
}
로그 파일은 다음과 같이 보일 수 있습니다
: 이[2017-01-01 13:15:13,932 INFO server.service.ControllerService - Filter:server.service.model.Filters]
[2017-01-01 15:36:04,914 INFO server.service.ControllerService - Filter:server.service.model.Filters]
[2017-01-01 15:55:50,279 ERROR server.service.WebClient - server API failed: [(someError.java:12345)]
{"someId":"etc","otherId":123,"token":{}}]
[2017-01-01 15:55:50,366 ERROR server.service.controller.Search - Server error for [/service/search/load]: java.lang.NullPointerException stack[etc]
java.lang.NullPointerException
at server.common.stack(SomeApi.java:123)
at server.service.trace(SomeService.java:456)
at java.lang.Thread.run(Thread.java:789)
etc.
etc.]
대신 나는이 얻을 :
2017-01-01 11:09:42,439 INFO server.service.function.property.PropertyService - Props (re)loaded.
2017-01-01 11:15:46,155 DEBUG server.service.ApiController - api/start called! params:
${params}
2017-01-01 13:01:29,675 ERROR server.service.util.base.FtpClient - Error retrieving file. Directory does not exist.
2017-01-01 13:15:12,803 DEBUG server.service.ApiController - api/start called! params:
${params}
2017-01-01 13:15:13,932 INFO server.service.ControllerService - Filter:server.service.model.Filters
2017-01-01 15:36:04,914 INFO server.service.ControllerService - Filter:server.service.model.Filters
2017-01-01 15:55:50,279 ERROR server.service.WebClient - server API failed: [(someError.java:12345)]
{"someId":"etc","otherId":123,"token":{}}
2017-01-01 15:55:50,366 ERROR server.service.controller.Search - Server error for [/service/search/load]: java.lang.NullPointerException stack[etc]
java.lang.NullPointerException
at server.common.stack(SomeApi.java:123)
at server.service.trace(SomeService.java:456)
at java.lang.Thread.run(Thread.java:789)
etc.
etc.
2017-01-01 16:17:55,175 DEBUG server.config.app -
STARTING...
2017-01-01 16:18:00,040 INFO server.common.service.base.property - Props (re)loaded.
2017-01-01 17:44:43,959 DEBUG server.service.controller - api/start called! params:
${params}
나는 그렙 여러 문자열을 읽는 예상 결과는 이것이다
[2017-01-01 13:15:13,932 INFO server.service.ControllerService - Filter:server.service.model.Filters]
[2017-01-01 15:36:04,914 INFO server.service.ControllerService - Filter:server.service.model.Filters]
[2017-01-01 15:55:50,279 ERROR server.service.WebClient - server API failed: [(someError.java:12345)]
{"someId":"etc","otherId":123,"token":{}}]
[2017-01-01 15:55:50,366 ERROR server.service.controller.Search - Server error for [/service/search/load]: java.lang.NullPointerException stack[etc]]
[java.lang.NullPointerException]
[ at server.common.stack(SomeApi.java:123)]
[ at server.service.trace(SomeService.java:456)]
[ at java.lang.Thread.run(Thread.java:789)]
[ etc.]
[ etc.]
나는 무엇을 했습니까? 보기? 이 방법으로 할 수 있습니까?
을 사용할 수 있어야합니다. Perl이나 Python과 같은 다른 것을 사용해야 할 것입니다. – Samadi
@Samadi,'-z'와 함께, 그것은 줄 단위가 아닙니다. –
@Asgair as aside - all-caps 변수 이름은 운영 체제 나 쉘에 의미가있는 변수에 사용되도록 POSIX에 의해 지정되는 반면, 하나 이상의 소문자가있는 이름은 응용 프로그램 용으로 예약됩니다. 당신은 후자의 클래스에서 이름을 사용해야합니다. 이후 버전의 쉘에 새로운 모든 대문자가 추가되면, 사용중인 아무 것도 우연히 덮어 쓰지 않게됩니다. –