如何在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地址(包括网络和广播地址).
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.
这在访问日志中对我来说很好.
cat access_log | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}'
让我们一个一个地打破它.
[0-9]{1,3}
表示[]中提到的范围的一到三次出现.在这种情况下,它是0-9.所以它匹配10或183等模式.
其次是'.'.我们需要将其作为'.'来逃避.是一个元字符,对shell有特殊意义.
所以现在我们的模式就像'123'.'12".等等
这种模式重复三次(带有'.').所以我们将它括在括号中.
([0-9]{1,3}\.){3}
最后,这种模式会重演,但这次没有'.'.这就是为什么我们在第3步中单独保留它. [0-9]{1,3}
如果ips位于每行的开头,就像我的情况一样:
egrep -o '^([0-9]{1,3}\.){3}[0-9]{1,3}'
其中'^'是一个锚点,告诉你在一行的开头搜索.
我通常从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)