2010-12-16 48 views
1

分析するインターネットトラフィックデータがあります。特定のIP範囲内にあるパケットだけを分析する必要があります。だから、私はifステートメントを書く必要があります。私は、テスト条件の正規表現が必要だと思います。正規表現の私の知識は少し弱いです。誰かがその条件の正規表現をどのように構築するか教えてもらえますか?例の範囲はPerl IPアドレス範囲の正規表現

Group A 
56.286.75.0/19 
57.256.106.0/21 
64.131.14.0/22 

Group B 
58.176.44.0/21 
58.177.92.0/19 

等であってもよいif文はので、私は「AでIP」と「BにおけるIP」の条件と同等の正規表現を作成する必要があります

if("IP in A" || "IP in B") { 
     do something 
} 

else { do something else } 

ようなものです。

+3

なぜビットレベルで定義された何かをチェックするためにregexを使いたいのですか? – x13n

+0

@ x13n井戸はちょうど最初の考えであり、私がここに投稿してより良いアイデアを得る理由の1つです。私は "ビットレベルで定義された"とはどういう意味か分かりませんでした。 – sfactor

+0

ネットワークマスク(各アドレスの/ 部分)は、アドレスがいくつかのサブネットに属するかどうかを判断するために、左のアドレスからいくつのビットを比較すべきかを示します。このために正規表現を書くのは難しいでしょう。 – x13n

答えて

8

私は正規表現がこの問題に大きな利点を提供するとは思わない。

代わりに、Net :: Netmaskモジュールを使用します。 "一致"メソッドは、あなたが望むことをする必要があります。

+0

ありがとう、私はこれを試してみましょう。 – sfactor

0

Martinは正しく、Net :: Netmaskを使用します。あなたが本当にかかわらず、正規表現を使用したい場合は...私はIPアドレスを確認するために正規表現を使用したとの不一致をエコーする必要が

$prefix = "192.168.1.0/25"; 
$ip1 = "192.168.1.1"; 
$ip2 = "192.168.1.129"; 

$prefix =~ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\/([0-9]+)/$mask=(2**32-1)<<(32-$5); $1<<24|$2<<16|$3<<8|$4/e; 
$ip1 =~ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/$1<<24|$2<<16|$3<<8|$4/e; 
$ip2 =~ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/$1<<24|$2<<16|$3<<8|$4/e; 

if (($prefix & $mask) == ($ip1 & $mask)) { 
    print "ip1 matches\n"; 
} 
if (($prefix & $mask) == ($ip2 & $mask)) { 
    print "ip2 matches\n"; 
} 
+0

賢いですが、それはPerlにラインノイズに類似した書き込み専用の混乱であるという悪い評判を得るようなコードです:) –

+3

合意。実際にはこれをしないでください。 – eater

+0

'[0-9] +'は、指定されたオクテットが0〜255の間だけである場合、IPアドレスの照合に使用する貧弱な文字クラスです。 '[12]?[1-5]?[0-9] \。'のようなものは、1つのオクテットを照合するのには優れていますが、まだ完全ではありません。これが、正規表現を使用してIPをマッチングさせるべきではない理由です。 :) – friedo

1

は...しかし、ここでのテキストのうち、IPアドレスを引くための方法です。

qr{ 
    (?<!\d)    # No digit having come immediately before 
    (?: [1-9] \d?  # any one or two-digit number 
    | 1 \d \d   # OR any three-digit number starting with 1 
    | 2 (?: [0-4] \d # OR 200 - 249 
     | 5 [0-6] # OR 250 - 256 
     ) 
) 
    (?: \.     # followed by a dot 
     (?: [1-9] \d?  # 1-256 reprise... 
     | 1 \d \d 
     | 2 (?: [0-4 \d 
      | 5 [0-6] 
      ) 
    ) 
){3}  # that group exactly 3 times 
    (?!\d) # no digit following immediately after   
}x 
; 

しかし、一般的なパターンでは、IPパーサーを構築できます。与えられたが、「範囲」のためにしかし、私はより少ない何もしないだろう、次

A => qr{ 
    (?<! \d) 
    (?: 56\.186\. 75 
    | 57\.256\.106 
    | 64\.131\. 14 
) 
    \. 
    (?: [1-9] \d? 
    | 1 \d \d 
    | 2 (?: [0-4] \d 
     | 5 [0-6] 
     ) 
) 
    (?! \d) 
    }x 

B => qr{ 
    (?<! \d) 
    58 \. 
    (?: 176\.44 
    | 177\.92 
) 
    \. 
    (?: [1-9] \d? 
    | 1 \d \d 
    | 2 (?: [0-4] \d 
     | 5 [0-6] 
     ) 
) 
    (?! \d) 
    }x 
+0

プレフィックスの長さ( '/'の後の数字)は、どのくらいのビットがあなたが一致しなければならない唯一の部分であるアドレスのネットワーク部分を構成します。ここでは、すべてが '/ 24'であることを前提とした最初の3オクテットにマッチするだけです。 http://en.wikipedia。org/wiki/CIDR_notation – eater

+0

ネットマスクモジュールを使用してビットを抽象化することを強くお勧めしますが、正規表現を使用するようにバインドされ、決定された場合(これはまさに私自身です:) '((DEFINE)...)'ブロックと "正規表現サブルーチン"を使って "文法"正規表現を使用してください。 – tchrist

+1

これはホイールを再発明しました - [Regexp :: Common :: net](http://search.cpan.org/perldoc?Regexp::Common::net)を使用してください。 – Ether

1

ように私が何かをやっている:私はネット経由NetAddr :: IPを選択しました

use NetAddr::IP; 

my @group_a = map NetAddr::IP->new($_), @group_a_masks; 
... 
my $addr = NetAddr::IP->new($ip_addr_in); 
if (grep $_->contains($addr), @group_a) { 
    print "group a"; 
} 

:: IPv6対応のネットマスク。