web-dev-qa-db-ja.com

Linuxシェルで正規表現を使用してファイルからIPアドレスを抽出するにはどうすればよいですか?

Linuxシェルで正規表現によってテキスト部分を抽出する方法は?たとえば、すべての行がIPアドレスであるが、別の位置にあるファイルがあるとします。一般的なUNIXコマンドラインツールを使用してこれらのIPアドレスを抽出する最も簡単な方法は何ですか?

57

grep を使用してそれらを引き出すことができます。

grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
115
brien

ここの例のほとんどは、技術的に有効なIPアドレスではない999.999.999.999に一致します。

以下は、有効なIPアドレス(ネットワークおよびブロードキャストアドレスを含む)のみで一致します。

grep -E -o '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' file.txt

一致した行全体を表示する場合は、-oを省略します。

41
Sarel Botha

正規表現を正しくするために、通常はgrepから始めます。

# [multiple failed attempts here]
grep    '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*'                 file  # good?
grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' file  # good enough

次に、それをsedに変換して、残りの行を除外します。 (このスレッドを読んだ後、あなたと私はもうそれをするつもりはありません。私たちはgrep -o代わりに)

sed -ne 's/.*\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\).*/\1/p  # FAIL

そのとき、私は通常、他の人と同じ正規表現を使用していないためにsedに悩まされます。そこで、Perlに移動します。

$ Perl -nle '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ and print $&'

どんな場合でもPerlは知っておくと良いでしょう。 CPANを少しだけインストールしている場合は、わずかなコストで信頼性を高めることもできます。

$ Perl -MRegexp::Common=net -nE '/$RE{net}{IPV4}/ and say $&' file(s)
11
JB.

これは、アクセスログでうまく機能します。

cat access_log | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}'

それを部分ごとに壊してみましょう。

  • [0-9]{1,3}は、[]に記載されている範囲が1〜3回出現することを意味します。この場合、0-9です。したがって、10や183などのパターンに一致します。

  • 「。」が続きます。これを「。」としてエスケープする必要があります。はメタ文字であり、シェルにとって特別な意味があります。

そのため、「123」のようなパターンになりました。 「12.」等.

  • このパターンは3回繰り返されます(「。」付き)。そのため、括弧で囲みます。 ([0-9]{1,3}\.){3}

  • 最後に、パターンは繰り返されますが、今回は「。」がありません。そのため、3番目のステップで個別に保管しました。 [0-9]{1,3}

私の場合のようにipsが各行の先頭にある場合:

egrep -o '^([0-9]{1,3}\.){3}[0-9]{1,3}'

ここで、「^」は行の先頭で検索するように指示するアンカーです。

11
Sankalp

このトピックに関する有益なブログ記事を書きました: 正規表現を使用してプレーンテキストからIPv4およびIPv6 IPアドレスを抽出する方法

この記事には、IPの最も一般的なさまざまなパターンの詳細なガイドがあり、通常は正規表現を使用してプレーンテキストから抽出および分離する必要があります。
このガイドは、必要に応じてIPアドレスの抽出と検出を処理するためのCodVerterの IP Extractor ソースコードツールに基づいています。

IPv4アドレスを検証およびキャプチャする場合、このパターンでジョブを実行できます。

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

またはPrefix(「スラッシュ表記」)でIPv4アドレスを検証およびキャプチャするには:

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?/[0-9]{1,2})\b

または、サブネットマスクまたはワイルドカードマスクをキャプチャするには:

(255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)

または、サブネットマスクアドレスを除外するには、正規表現 negative lookahead を使用して行います。

\b((?!(255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)[.](255|254|252|248|240|224|192|128|0)))(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)[.]){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

IPv6検証については、この回答の上部に追加した記事のリンクにアクセスできます。
すべての一般的なパターンをキャプチャする例は次のとおりです(CodVerterのIP Extractorヘルプサンプルから取得)。

enter image description here

希望する場合は、IPv4正規表現 here をテストできます。

3
jonathana

ログファイルをよりよく見るために少し script を書きました。これは特別なことではありませんが、Perlを学んでいる多くの人々にとって役立つかもしれません。 IPアドレスを抽出した後、IPアドレスでDNSルックアップを行います。

3
James

grep -E -o "([0-9] {1,3} [。]){3} [0-9] {1,3}"

2
shaa0601

作成したシェルヘルパーを使用できます。 https://github.com/philpraxis/ipextract

便宜上、ここにそれらを含めました。

#!/bin/sh
ipextract () 
{ 
egrep --only-matching -E  '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' 
}

ipextractnet ()
{ 
egrep --only-matching -E  '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[[:digit:]]+' 
}

ipextracttcp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/tcp' 
}

ipextractudp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/udp' 
}

ipextractsctp ()
{ 
egrep --only-matching -E  '[[:digit:]]+/sctp' 
}

ipextractfqdn ()
{ 
egrep --only-matching -E  '[a-zA-Z0-9]+[a-zA-Z0-9\-\.]*\.[a-zA-Z]{2,}' 
}

(ipextractファイルに保存されている場合)シェルからロード/ソースします:

$ ipextract

それらを使用します:

$ ipextract < /etc/hosts
127.0.0.1
255.255.255.255
$

実際の使用例:

ipextractfqdn < /var/log/snort/alert | sort -u
dmesg | ipextractudp
2
Phil L.

sed を使用できます。しかし、Perlを知っているなら、それは長期的に知るのが簡単で、より便利かもしれません:

Perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
2
Avi

ApacheログからIPアドレスを取得し、IPアドレスがWebサイトにアクセスした回数のリストを表示するための簡単なソリューションが必要な場合は、次の行を使用します。

grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' error.log | sort | uniq -c | sort -nr > occurences.txt

ハッカーを禁止する良い方法。次にできること:

  1. 訪問数が20未満の行を削除します
  2. 正規表現を使用して、単一のスペースまでカットして、IPアドレスのみを持つようにします
  3. 正規表現を使用すると、IPアドレスの最後の1〜3の数が削減されるため、ネットワークアドレスのみが得られます。
  4. 追加 deny fromおよび各行の先頭にスペース
  5. 結果ファイルを.htaccessとして配置します
1
pbies

Awkも使用できます。何かのようなもの ...

awk '{i = 1; if(NF> 0)do {if($ i〜/ regexp /)print $ i; i ++;} while(i <= NF);} 'ファイル

-クリーニングが必要な場合があります。基本的にawkでそれを行う方法を示すための、迅速で汚い応答

0
Allen Ratcliff

私はすべての回答を試しましたが、それらのすべてに1つまたは複数の問題があり、そのうちのいくつかをリストします。

  1. いくつかは有効なIPとして123.456.789.111を検出しました
  2. 127.0.00.1が有効なIPとして検出されないものもあります
  3. 08.8.8.8のようなゼロで始まるIPを検出しないものもあります

したがって、ここでは上記のすべての条件で機能する正規表現を投稿します。

注:次の正規表現で問題なく200万以上のIPを抽出しました。

(?:(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)\.){3}(?:1\d\d|2[0-5][0-5]|2[0-4]\d|0?[1-9]\d|0?0?\d)
0
Mohsen Sarkar

前の回答にはすべて1つ以上の問題があります。受け入れられた回答は、999.999.999.999のようなIP番号を許可します。現在2番目に上位の回答には、127.0.0.1または8.8.8.8ではなく、127.000.000.001または008.008.008.008などの0のプレフィックスが必要です。 Apamaではほぼ正しいのですが、この式ではipnumberが行の唯一のものであり、先頭または末尾のスペースは許可されておらず、行の途中からipを選択することもできません。

正しい正規表現は http://www.regextester.com/22 で見つけることができると思います

したがって、ファイルからすべてのIPアドレスを抽出する場合は、次を使用します。

grep -Eo "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" file.txt

重複したくない場合:

grep -Eo "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])" file.txt | sort | uniq

この正規表現にまだ問題がある場合はコメントしてください。この問題の多くの間違った正規表現を見つけるのは簡単です。この問題に本当の問題がないことを望みます。

0
anneb

ここの誰もが本当に長年の正規表現を使用していますが、実際にPOSIXの正規表現を理解すると、IPアドレスの印刷にこのような小さなgrepコマンドを使用できます。

grep -Eo "(([0-9]{1,3})\.){3}([0-9]{1,3})"

(補足)これは無効なIPを無視しませんが、非常に簡単です。

0
Yokai

Perlをお勧めします。 (\ d +。\ d +。\ d +。\ d +)がおそらくうまくいくはずです。

編集:完全なプログラムのようにするだけで、次のようなことができます(テストされていません):

#!/usr/bin/Perl -w
use strict;

while (<>) {
    if (/(\d+\.\d+\.\d+\.\d+)/) {
        print "$1\n";
    }
}

これは、行ごとに1つのIPを処理します。 1行に複数のIPがある場合は、/ gオプションを使用する必要があります。 man perlretutは、正規表現に関するより詳細なチュートリアルを提供します。

0
PolyThinker