2

これらの一連のデータからすべての「インターフェース名」を出力する解析スクリプトをPerlで記述したいと思います。

interfaces.ifTable.ifEntry.ifDescr.1 : OCTET STRING- (ascii): (hex): length = 30
    0:  53 6f 66 74 77 61 72 65 20 4c 6f 6f 70 62 61 63     Software Loopbac
    16:  6b 20 49 6e 74 65 72 66 61 63 65 20 31 00 -- --     k Interface 1...

interfaces.ifTable.ifEntry.ifDescr.2 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 53 53     WAN Miniport (SS
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

interfaces.ifTable.ifEntry.ifDescr.3 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 4c 32     WAN Miniport (L2
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

3つのインターフェイスの名前をすべて(「ソフトウェアループバックインターフェイス1」、「WANミニポート(SSTP)」、「WANミニポート(L2TP)」)として抽出し、さらに処理を行います。正規表現を使ってみましたが、ルーチはありませんでした。これを行う簡単な方法はありますか?前もって感謝します!

4

4 に答える 4

1

以下は、入力例を前提として、必要なことを実行する迅速で汚いperlスクリプトです。入力形式の変更を適切に処理しません。ファイルから入力を取得するスクリプトを作成しました。これを変更する必要があります。

open(INPUT, "interfaces.txt");

my $interface;

while(<INPUT>) {
        if (/^\s*0:/) {
                $interface = substr($_, 60, 16);
        } elsif (/^\s*16:/) {
                $interface .= substr($_, 61, 16);

                $interface =~ s/\.+$//;

                print $interface, "\n";
        }
}

close(INPUT);
于 2012-06-22T04:16:17.100 に答える
1

これはまた別の汚いperlスクリプトです。必要に応じてデータを$textに読み込みます。正規表現は、各16進ダンプ行のパターンを探します。次に、結合行は16進値を文字列に再結合し、現在の累積インターフェース名に追加します。mttrbの方が簡単です。;)

$text =<<EOM;
interfaces.ifTable.ifEntry.ifDescr.1 : OCTET STRING- (ascii): (hex): length = 30
    0:  53 6f 66 74 77 61 72 65 20 4c 6f 6f 70 62 61 63     Software Loopbac
    16:  6b 20 49 6e 74 65 72 66 61 63 65 20 31 00 -- --     k Interface 1...

interfaces.ifTable.ifEntry.ifDescr.2 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 53 53     WAN Miniport (SS
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

interfaces.ifTable.ifEntry.ifDescr.3 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 4c 32     WAN Miniport (L2
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............
EOM

$interface = "";
foreach $line (split(/\n/, $text)) {
  next unless $line =~ /\b(\d+):\s+((?:[0-9a-fA-F-]{2} ){16})/;
  if ($1 == 0) {
    print "$interface\n" if $interface;
    $interface = "";
  }
  $interface .= join('', map { chr(hex($_)) } grep { $_ ne '--' && $_ ne '00' } split(/ /, $2));
}
print "$interface\n" if $interface;

結合線を説明するために、その線では次のことが発生します。

  1. split(/ /、$ 2)-正規表現から2番目に保存されたグループ(16進文字)を取得し、それを数字の各ペアを含む配列に分割します。
  2. grep {$ _ ne'-' && $ _ ne '00'}-数字のペアの配列を調べ、'-'および'00'エントリを除外して、有効な値のみを残します。
  3. map {chr(hex($ ))}-フィルタリングされた各ペアに対して式を実行します。$は処理中のペアです。16進数は、それをhex()文字列から数値に解析し、chr()はその数値を取得して、対応する文字に変換します。
  4. join(''、...)-マップが作成した文字の配列を取り込み、それらから単一の文字列を作成します。''は、各配列項目を区切る文字列です。この場合は何もありません。
于 2012-06-22T04:30:04.533 に答える
1

段落モード(設定$/ = "")を使用すると、各レコードを読み取り、行を個別に処理できます。16進数の数は一定であるように思われるため、最後のフィールドを取得するのは、フィールドsplitの固定を使用して空白で行うのが最も簡単なようです。最後のフィールドが必要です。LIMIT

use strict;
use warnings;
use Data::Dumper;

$/ = "";  # paragraph mode keeps lines together

while (<DATA>) {
    chomp;   # removes two newlines after we changed $/
    my ($hdr, @data) = split /\n/; # header + 2 lines
    my ($interface, @nums) = getdata(@data);
    print Dumper $interface;
}
sub getdata {
    my (@hex, $str);
    my @data = @_;
    for (@data) {
        push @hex, split(' ', $_, 18);  # LIMIT set to 18
        $str .= pop @hex;               # last field is our string
    }
    return $str, @hex;   # return everything, why not?
}

__DATA__
interfaces.ifTable.ifEntry.ifDescr.1 : OCTET STRING- (ascii): (hex): length = 30
    0:  53 6f 66 74 77 61 72 65 20 4c 6f 6f 70 62 61 63     Software Loopbac
    16:  6b 20 49 6e 74 65 72 66 61 63 65 20 31 00 -- --     k Interface 1...

interfaces.ifTable.ifEntry.ifDescr.2 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 53 53     WAN Miniport (SS
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

interfaces.ifTable.ifEntry.ifDescr.3 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 4c 32     WAN Miniport (L2
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

出力:

$VAR1 = 'Software Loopback Interface 1...';
$VAR1 = 'WAN Miniport (SSTP).............';
$VAR1 = 'WAN Miniport (L2TP).............';
于 2012-06-22T05:08:06.663 に答える
1

正規表現を使用した別の解決策。

use strict ;
use warnings;
my $Data = '
interfaces.ifTable.ifEntry.ifDescr.1 : OCTET STRING- (ascii): (hex): length = 30
    0:  53 6f 66 74 77 61 72 65 20 4c 6f 6f 70 62 61 63     Software Loopbac
    16:  6b 20 49 6e 74 65 72 66 61 63 65 20 31 00 -- --     k Interface 1...

interfaces.ifTable.ifEntry.ifDescr.2 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 53 53     WAN Miniport (SS
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............

interfaces.ifTable.ifEntry.ifDescr.3 : OCTET STRING- (ascii): (hex): length = 20
    0:  57 41 4e 20 4d 69 6e 69 70 6f 72 74 20 28 4c 32     WAN Miniport (L2
    16:  54 50 29 00 -- -- -- -- -- -- -- -- -- -- -- --     TP).............
';

foreach my $Record ( $Data =~ m#\G(.+?)(?:(?=^\s*$)|\z)#gsm)  {
    my $Interface = '';
    foreach ( split /\n/, $Record ) {
        next if /^\s*$/;
        next if /OCTET STRING/i;
        (m#^[^:]+:(?:\s*(?:\w\w|--)\s*){16}(.+)$#);
        $Interface .= "$1";
    }

    print "$Interface\n";
}
于 2012-06-22T06:57:34.897 に答える