你如何从Linux文件中使用正则expression式提取IP地址?
如何在Linux shell中通过regexp提取文本部分? 可以这么说,我在每一行都有一个IP地址,但是在不同的位置。 使用常用的unix命令行工具提取这些IP地址的最简单方法是什么?
你可以用grep把它们拉出来。
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
这里的大多数例子都会在999.999.999.999上匹配,这在技术上并不是有效的IP地址。
以下内容仅适用于有效的IP地址(包括networking地址和广播地址)。
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开始,正确地得到正则expression式。
# [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
那时候我通常会因为不使用和其他人相同的正则expression式而恼火于sed
。 所以我搬到perl
。
$ perl -nle '/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/ and print $&'
无论如何,Perl都是很好的例子。 如果你已经安装了less量的CPAN,你甚至可以用很less的成本使它更可靠:
$ 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}
表示在[]中提到的一到三个范围。 在这种情况下,它是0-9。 所以它匹配10或183的模式。 -
后面跟着一个'。'。 我们将需要逃避这个'。' 是一个元字符,对壳有特殊的意义。
所以现在我们处于“123”模式。 '12“。 等等
-
这种模式重复三次(用'。')。 所以我们把它括在括号里。
([0-9]{1,3}\.){3}
-
最后这个模式重演,但是这次没有'。'。 这就是为什么我们在第三步分开保存它的原因。
[0-9]{1,3}
如果ips位于每行的开头,就像我的情况一样:
egrep -o '^([0-9]{1,3}\.){3}[0-9]{1,3}'
其中“^”是指示在行首开始search的锚点。
我写了一个脚本来更好地查看我的日志文件,没有什么特别的,但是可能会帮助很多正在学习perl的人。 在提取IP地址后,它会对IP地址进行DNS查找。
grep -E -o“([0-9] {1,3} [。]){3} [0-9] {1,3}”
你可以使用一些我所做的shell帮助程序: 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,}' }
从shell中加载它(当存储在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
我build议perl。 (\ d +。\ d +。\ d +。\ d +)应该可以做到这一点。
编辑:只是为了使它更像一个完整的程序,你可以做下面的事情(未经testing):
#!/usr/bin/perl -w use strict; while (<>) { if (/(\d+\.\d+\.\d+\.\d+)/) { print "$1\n"; } }
这每行处理一个IP。 如果每行有多个IP,则需要使用/ g选项。 man perlretut给你一个正则expression式的更详细的教程。
你也可以使用awk。 就像是 …
awk'{i = 1; if(NF> 0)do {if($ i〜/ regexp /)print $ i; i ++;} while(i <= NF);}'文件
– 可能需要清洁。 只是一个快速和肮脏的反应,基本上显示如何用awk做到这一点
如果你没有给出一个特定的文件,你需要提取IP地址,那么我们需要recursion地做。 grep命令 – >search文本或文件以匹配给定的string并显示匹配的string。
grep -roE'[0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}'| grep -oE'[0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}'
-r – >我们可以search整个目录树,即当前目录和所有级别的子目录。 它表示recursionsearch。
-o – >仅打印匹配的string
-E – >使用扩展的正则expression式
如果我们不会在pipe道之后使用第二个grep命令,那么我们将获得IP地址以及它所在的path
cat ip_address.txt | grep '^[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[,].*$\|^.*[,][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[,].*$\|^.*[,][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}$'
让我们假设该文件是逗号分隔的,并在开始,结束和中间的某个地方的IP地址的位置
第一个正则expression式查找行首的IP地址的完全匹配。 第二个正则expression式在中间或后面查找ip地址,我们匹配的方式是后面的数字应该是1到3位数字,像12345.12.34.1这样的falsy ips可以排除在外。
第三个正则expression式在行尾查找ip地址
所有以前的答案都有一个或多个问题。 接受的答案允许IP号码,如999.999.999.999。 当前第二个最高的答案要求前缀为0,例如127.000.000.001或008.008.008.008,而不是127.0.0.1或8.8.8.8。 Apama几乎是正确的,但是expression式要求ipnumber是唯一的行,不允许前导或尾随空间,也不能从一行中selectip。
我认为正确的正则expression式可以在http://www.regextester.com/22find
所以,如果你想从一个文件中提取所有的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
请评论如果在这个正则expression式仍然有问题。 这个问题很容易find很多错误的正则expression式,我希望这个没有真正的问题。
对于centos6.3
ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | awk 'BEGIN {FS=":"} {print $2}'