이 명령을 사용하여 아래 원시 로그에서 다음 정보를 추출했습니다.
echo -e "Timestamp\t\tEmailTo:\t\tEmailFrom:\t\t\t\t\tIPAddress:\tErrorCodes:" && sed -n -e 's/.*\([0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9]*\) .*\([0-9][0-9]:[0-9][0-9]:[0-9][0-9]*\).*/\1 \2 /p' logs
산출:
Timestamp EmailTo: EmailFrom: IPAddress: ErrorCodes:
2017-01-02 12:50:00
2017-01-02 13:10:25
원본 로그:
2017-01-02 12:50:00 1cNxNS-001NKu-9B == [email protected] R=dkim_lookuphost T=dkim_remote_smtp defer (-45) H=mta6.am0.yahoodns.net [98.138.112.38]: SMTP error from remote mail server after MAIL FROM:<[email protected]> SIZE=1772: 421 4.7.0 [TSS04] Messages from 192.168.1.269 temporarily deferred due to user complaints - 4.16.55.1; see https://help.yahoo.com/kb/postmaster/SLN3434.html
2017-01-02 13:10:25 1cNxhD-001VZ3-0f == [email protected] ([email protected]) <[email protected]> R=lookuphost T=remote_smtp defer (-45) H=mta7.am0.yahoodns.net [98.138.112.34]: SMTP error from remote mail server after MAIL FROM:<[email protected]> SIZE=87839: 500 5.9.0 [TSS04] Messages from 192.168.1.269 temporarily deferred due to user complaints - 4.16.55.1; see https://help.yahoo.com/kb/postmaster/SLN3434.html
하지만 필요한 다른 정보는 추출할 수 없습니다.
Timestamp EmailTo: mailFrom: IPAddress: ErrorCodes:
2017-01-02 12:50:00 [email protected] [email protected] 192.168.1.269 421 4.7.0
2017-01-02 13:10:25 [email protected] [email protected] 192.168.1.269 500 5.9.0
을 사용하여 모든 정보를 추출하는 방법은 무엇입니까 sed
?
답변1
다음 표현을 시도해 볼 수 있습니다 sed
.
sed -e 's/^\(.* .* \).* .*== \([^ ]* \).*MAIL FROM:<\([^ ]*\)> [^ ]* \([0-9 .]*\)\[.*Messages from \([^ ]*\).*$/\1\t\2\t\3\t\5\t\4/'
귀하의 예에서는 저에게 효과적이었습니다.
설명하다
표현식 sed
에는 단 하나의 명령( )만 포함되어 있습니다 s/.../.../
.
첫 번째 부분 s///
:
'^\(.* .* \)' -- Timestamp, two first space-separated blocks of text, \1.
'.* .*== ' -- Uninteresting text after timestamp.
'\([^ ]* \)' -- Block of test between spaces, first email address, \2.
'.*MAIL FROM:<' -- Position before second email.
'\([^ ]*\)>' -- Second email addr, non-space characters, ended by '>', \3.
' [^ ]* ' -- SIZE=...:
'\([0-9 .]*\)\[' -- Error codes: digits, spaces and dots ended by '[', \4.
'.*Messages from ' -- Position before IP.
'\([^ ]*\)' -- Non-space characters, ended by space, IP. \5.
'.*$' -- Text before end of string, not interesting.
보시다시피 이것은 원본 로그에 대한 직접적인 설명일 뿐 흥미롭지는 않습니다.
두 번째 부분은 (탭 문자)를 올바른 순서 로 구분 기호로 배치하는 s///
것입니다 .\N
\t
답변2
나는 awk에 대한 경험이 많지 않지만 시도해 보고 싶습니다. 나는 당신이 얼마나 많은 로그 라인을 얻고 싶은지 모르기 때문에 이것이 매우 취약하다고 생각합니다.
어쨌든 이것은 BEGIN
블록을 사용하여 선택할 변수를 설정하고 제목을 표시하기 전에 인쇄할 형식 문자열을 사용합니다. Time 및 EmailTo는 예측 가능하므로 세 가지 정규식 세트( $1
, $2
및 $5
) 앞에 숫자 필드를 사용할 수 있습니다. 이는 매우 대략적인 작업입니다. 개선을 위한 어떤 제안이라도 대단히 감사하겠습니다!
awk 'BEGIN {
from=""; ip=""; error=""; fstr="%-24s%-24s%-40s%-16s%s\n";
printf(fstr, "Timestamp:", "EmailTo:", "EmailFrom:", "IPAddress:", "ErrorCodes:");
}
{ for (i=6; i<NF; i++)
{
# From Address
if ($i ~ /FROM:<[^ ]*>/)
from=substr($i, 7, length($i)-7);
# Errors found in two adjacent fields.
if ($(i-1) ~ /[[:digit:]]{3}/ && $i ~ /[[:digit:]]\.[[:digit:]]\.[[:digit:]]/)
error=$(i-1) " " $i;
# From address after predictable string.
if ($(i-2) " " $(i-1) == "Messages from" && $i ~ /[[:digit:].]{7,15}/)
ip=$i;
}
printf(fstr, $1" "$2, $5, from, ip, error);
}' logs