Linuxシェルで正規表現によってテキスト部分を抽出する方法は?たとえば、すべての行がIPアドレスであるが、別の位置にあるファイルがあるとします。一般的なUNIXコマンドラインツールを使用してこれらのIPアドレスを抽出する最も簡単な方法は何ですか?
grep を使用してそれらを引き出すことができます。
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
ここの例のほとんどは、技術的に有効な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を省略します。
正規表現を正しくするために、通常は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)
これは、アクセスログでうまく機能します。
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}'
ここで、「^」は行の先頭で検索するように指示するアンカーです。
このトピックに関する有益なブログ記事を書きました: 正規表現を使用してプレーンテキストから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ヘルプサンプルから取得)。
希望する場合は、IPv4正規表現 here をテストできます。
ログファイルをよりよく見るために少し script を書きました。これは特別なことではありませんが、Perlを学んでいる多くの人々にとって役立つかもしれません。 IPアドレスを抽出した後、IPアドレスでDNSルックアップを行います。
grep -E -o "([0-9] {1,3} [。]){3} [0-9] {1,3}"
作成したシェルヘルパーを使用できます。 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
sed を使用できます。しかし、Perlを知っているなら、それは長期的に知るのが簡単で、より便利かもしれません:
Perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
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
ハッカーを禁止する良い方法。次にできること:
deny from
および各行の先頭にスペースAwkも使用できます。何かのようなもの ...
awk '{i = 1; if(NF> 0)do {if($ i〜/ regexp /)print $ i; i ++;} while(i <= NF);} 'ファイル
-クリーニングが必要な場合があります。基本的にawkでそれを行う方法を示すための、迅速で汚い応答
私はすべての回答を試しましたが、それらのすべてに1つまたは複数の問題があり、そのうちのいくつかをリストします。
123.456.789.111
を検出しました127.0.00.1
が有効なIPとして検出されないものもあります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)
前の回答にはすべて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
この正規表現にまだ問題がある場合はコメントしてください。この問題の多くの間違った正規表現を見つけるのは簡単です。この問題に本当の問題がないことを望みます。
ここの誰もが本当に長年の正規表現を使用していますが、実際にPOSIXの正規表現を理解すると、IPアドレスの印刷にこのような小さなgrep
コマンドを使用できます。
grep -Eo "(([0-9]{1,3})\.){3}([0-9]{1,3})"
(補足)これは無効なIPを無視しませんが、非常に簡単です。
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は、正規表現に関するより詳細なチュートリアルを提供します。