다음과 같은 로그 파일이 있습니다.
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-RTP-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-Control-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
policy-map AutoQoS-Police-CiscoPhone
SWEs-elmPCI-A-01(config-pmap)#
%
이제 해시가 포함된 줄 사이에 기호로 시작하는 모든 줄을 찾아 #
다른 오류 로그 파일에 넣어야 합니다.
위의 시나리오를 고려한다면 이는 오류 로그 파일에 들어가야 합니다.
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-RTP-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-Control-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
답변1
이것이 당신이 원하는 것인지 확실하지 않지만 다음과 같습니다.
#!/bin/bash
awk '
BEGIN {
err=0
}
/^SWE.*#$/ {
if (err) {
printf "%s\n%s", txt, $0
txt=""
err=0
} else {
txt=$0
}
next
}
/^% Invalid/ {
err=1
txt=txt "\n" $0
next
}
{
txt=txt "\n" $0
}
END {
print ""
}
' "$1"
결과:
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-RTP-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-Control-Trust
^
% Invalid input detected at '^' marker.
SWEs-elmPCI-A-01(config)#
대안으로 내 생각은 그룹화를 위해 추가 행을 사용하는 것입니다.
awk '
BEGIN {
i = 0
sep="------------------------------------------------"
}
/^% Invalid/ {
printf "%s %3d\n%s\n%s\n%s\n",
sep, ++i, txt, $0, sep
txt=""
next
}
/^SWE.*#$/ {
txt=$0
next
}
txt != "" {
txt=txt "\n" $0
}
' "$1"
결과:
------------------------------------------------ 1
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-RTP-Trust
^
% Invalid input detected at '^' marker.
------------------------------------------------
------------------------------------------------ 2
SWEs-elmPCI-A-01(config)#
class AutoQoS-VoIP-Control-Trust
^
% Invalid input detected at '^' marker.
------------------------------------------------
답변2
어쩌면 다음과 같은 것일 수도 있습니다.
sed 'H;/#$/!d;s/^/\
/;x;/\n%/!d;s/.//;x;s/.*//;x'
오류 전후에 프롬프트가 필요하기 때문에 이 프롬프트에는 둘 다 포함되지만 예제 출력과 일치하도록 한 오류 이후와 다음 오류 이전에 나타나는 프롬프트는 포함되지 않습니다.
오류가 서로 이어지는지 여부에 관계없이 두 개의 힌트를 포함하면 훨씬 더 간단해질 것입니다.
sed 'H;/#$/!d;x;/\n%/!d'
오류가 발생하기 전에 힌트를 원하는 경우에도 훨씬 간단합니다.
sed '/#$/!{H;d;}
x;/\n%/!d'
아마도 이것을 설명하는 가장 좋은 방법은 와 같은 좀 더 장황한 언어로 번역하는 것입니다 perl
. 에서 sed
홀드 공간은 빈 줄로 초기화된 정적 변수와 같은 반면, 패턴 공간은 sed
입력의 각 줄에 차례로 할당되는 변수 입니다. . 그것은 다음과 같습니다:
$hold_space = "\n";
LINE: while ($pattern_space = <>) {
<sed commands go here>
print $pattern_space; # unless -n option is passed
}
이 H
명령은 다음과 같이 번역됩니다.
$hold_space .= $pattern_space;
이 d
명령은 다음과 같이 번역됩니다.
next LINE;
즉, 명령 실행을 중지하고 패턴 공간을 버리고 다음 입력 줄부터 다시 시작합니다.
x
스왑 모드 및 홀드 공간:
($pattern_space, $hold_space) = ($hold_space, $pattern_space);
따라서 마지막 sed
명령은 다음과 같이 변환됩니다.
$hold_space = "\n";
LINE: while ($pattern_space = <>) {
if (! ($pattern_space =~ /#$/)) { # anything other than a prompt
$hold_space .= $pattern_space;
next LINE;
}
($pattern_space, $hold_space) = ($hold_space, $pattern_space);
if (! ($pattern_space =~ /\n%/)) {
next LINE;
}
print $pattern_space;
}
다음과 같이 더 읽기 쉬운 방식으로 다시 작성할 수 있습니다.
LINE: while ($pattern_space = <>) {
if ($pattern_space =~ /#$/)) {
if ($hold_space =~ /\n%/)) {
print $hold_space;
}
$hold_space = $pattern_space;
} else {
$hold_space .= $pattern_space;
}
}
$pattern_space
이름을 to $line
및 $hold_space
to로 바꾸면 $current_block
더 명확해집니다.