2

基本的に私のコンピューターのnmapの出力である「perlthisfile.txt」というファイルを読み込もうとしています。

IP アドレスだけを出力したいので、次のコードを書きましたが、機能しません。

#!/usr/bin/perl  
use strict;  
use warnings;  
use Scalar::Util qw(looks_like_number);

print"\n running \n";
open (MYFILE, 'perlthisfile.txt') or die "Cannot open file\n";

while(<MYFILE>) {
    chomp;
    my @value = split(' ', <MYFILE>);
    print"\n before foreach \n";
    foreach my $val (@value) {
        if (looks_like_number($val)) {
            print "\n looks like number block \n";
            if ($val == /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5})/) {
                print "\n$val\n";
            }
        }
    }
}
close(MYFILE);
exit 0;

そして、このコードを実行したときの出力は次のとおりです。

  running 
  before foreach 
  before foreach 
  looks like number block 
  before foreach 
  looks like number block 
  before foreach 
  looks like number block

私のperlthisfile.txt:

  Starting Nmap 6.00 ( http://nmap.org ) at 2013-10-16 22:59 EST
  Nmap scan report for BoB2.iiNet (10.1.1.1)
  Nmap scan report for android-fbff3c3812154cdc (10.1.1.3)
  All 1000 scanned ports on android-fbff3c3812154cdc (10.1.1.3) are closed
  Nmap scan report for 10.1.1.5
  All 1000 scanned ports on 10.1.1.5 are open|filtered
  Nmap scan report for 10.1.1.6
  All 1000 scanned ports on 10.1.1.6 are closed
4

3 に答える 3

3

ここでいくつかの問題。@toolicが言ったように、<MYFILE>内部で呼び出すことsplitはおそらくあなたが望むものではありません - ファイルから次のレコードを読み取るので、$_代わりに使用してください。

また、==正規表現を使用している場合は、バインド演算子を使用する必要があります=~( Perl では数値比較に==のみ使用されます)。

if ($val =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5})/){

looks_like_number正規表現が機能する場合、それは冗長であることをお勧めします。使用している perl のバージョンに応じて次の==ような結果が得られるため、使用していると思われます。isn't numeric in numeric eq (==)

于 2013-10-16T13:07:38.427 に答える
2

いくつかのエラーがありました。そのうちの 1 つは、ポート番号のオプション部分が必要な正規表現です (:および次の\d{1,5}) 。

#!/usr/bin/perl  
use strict;  
use warnings;  

open (my $MYFILE, '<', 'perlthisfile.txt') or die $!;

my $looks_like_ip = qr/( \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} (?: : \d{1,5})? )/x;
while (<$MYFILE>) {
    chomp;
    my @value = split;
    print"\n before foreach \n";
    foreach my $val (@value) {
      if (my ($match) = $val =~ /$looks_like_ip/){
        print "\n$match\n";
      }
      # else { print "$val doesn't contain IP\n" }
    }
}
close($MYFILE) or warn $!;
于 2013-10-16T13:14:15.793 に答える
2

これが IP を抽出するための簡単なハックであると思われる場合は、次のような単純なものでうまくいく可能性があります。

perl -nlwe '/((?:\d+\.)+\d+)/ && print $1' perlthisfile.txt

つまり、決して厳密な正規表現ではなく、ピリオドで結合された数字に一致するだけです。一意の IP のみを出力したい場合は、ハッシュを使用して重複排除できます。

perl -nlwe '/((?:\d+\.)+\d+)/ && !$seen{$1}++ && print $1" perlthisfile.txt

ポート番号にも一致する少し厳密な正規表現を使用すると、次のようになります。

perl -nlwe '/((?:\d+[\.:]){3,4}\d+)/ && print $1' perlthisfile.txt

これにより、より短い番号のチェーンが許可されなくなり、ポート番号が許可されます。

この最後の正規表現は次のように説明しています。

/(         # opening parenthesis, starts a string capture
  (?:      # a non-capturing parenthesis
    \d+    # match a number, repeated one or more times
    [\.:]  # [ ... ] is a character class, it matches one of the literal 
           # characters inside it, and only one time
  ){3,4}   # closing the non-capturing parenthesis, adding a quantifier
           # that says this parenthesis can match 3 or 4 times
  \d+      # match one or more numbers
 )/x       # close capturing parenthesis (added `/x` switch)

この/xスイッチは、コメントと空白を使用して、上記の正規表現をそのまま使用できるようにするためのものです。

この背後にあるロジックは単純です: 数値の後にピリオドまたはコロンが続く文字列が必要です。この文字列が 3 回または 4 回必要です。別の番号で終了します。

+とは量指定子であり、その{3,4}左側の項目が何回一致するかを示します。デフォルトでは、すべての項目が 1 回一致しますが、量指定子を使用してこれを変更できます。+は の省略形で{1,}あり、次のものもあります。

  • ? -> {1,0}
  • * -> {0,}

構文は{min,max}で、数字が欠落している場合は、可能な限り何度でも意味します。

于 2013-10-16T13:34:46.573 に答える