
次のログファイルがあります。
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'
エラーの前後にプロンプトが必要なため、このプロンプトには両方が含まれますが、出力例と一致するようにしたエラーの後と次のエラーの前に表示されるプロンプトは含まれません。
エラーが互いにつながるかどうかにかかわらず、2つのヒントを含めると、はるかに簡単になります。
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
より明確になります。