如何在linux shell中通过regexp提取文本部分?可以说,我有一个文件,其中每一行都是一个IP地址,但位于不同的位置。使用常见的unix命令行工具提取这些IP地址的最简单方法是什么?
答案 0 :(得分:112)
您可以使用grep将它们拉出来。
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' file.txt
答案 1 :(得分:41)
此处的大多数示例都匹配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。
答案 2 :(得分:11)
这在访问日志中对我来说很好。
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}'
其中' ^'是一个锚点,告诉你在一行的开头搜索。
答案 3 :(得分:11)
我通常从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)
答案 4 :(得分:3)
我写了一点script来更好地查看我的日志文件,这没什么特别的,但可能会帮助很多正在学习perl的人。它在提取IP地址后对其进行DNS查找。
答案 5 :(得分:3)
我写了一篇有关此主题的内容丰富的博客文章:How to Extract IPv4 and IPv6 IP Addresses from Plain Text Using Regex。
本文详细介绍了IP的最常见不同模式,通常需要使用正则表达式将它们从纯文本中提取和隔离。
本指南基于CodVerter的IP Extractor源代码工具,用于在必要时处理IP地址提取和检测。
如果您希望验证并捕获IPv4地址,则可以使用此模式:
<h2 style="box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: 500; line-height: 1.2; margin: 20px 0px; font-size: 25px; padding-bottom: 10px; background-color: #ffffff;">Title Heading</h2>
或使用前缀(“斜杠表示法”)验证并捕获IPv4地址:
<h2>Title Heading</h2>
或捕获子网掩码或通配符掩码:
<p>, <a>, etc...
或过滤掉子网掩码地址,您可以使用正则表达式negative lookahead:
\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
对于 IPv6 验证,您可以转到我在此答案顶部添加的文章链接。
这是捕获所有常见模式的示例(摘自CodVerter的IP提取器帮助示例):
如果愿意,可以测试IPv4正则表达式here。
答案 6 :(得分:2)
你可以使用我制作的一些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
答案 7 :(得分:2)
grep -E -o“([0-9] {1,3} [。]){3} [0-9] {1,3}”
答案 8 :(得分:1)
您可以使用sed。但是如果你知道perl,从长远来看,这可能会更容易,也更有用:
perl -n '/(\d+\.\d+\.\d+\.\d+)/ && print "$1\n"' < file
答案 9 :(得分:0)
您也可以使用awk。有点像...
awk'{i = 1;如果(NF> 0)做{if($ i~ / regexp /)print $ i; i ++;} while(i&lt; = NF);}'file
- 可能需要清洁。只是一个快速而肮脏的响应,基本上显示如何使用awk
答案 10 :(得分:0)
我建议perl。 (\ d +。\ d +。\ d +。\ d +)应该可以做到这一点。
编辑:只是为了让它更像一个完整的程序,你可以做类似以下的事情(未经测试):
#!/usr/bin/perl -w
use strict;
while (<>) {
if (/(\d+\.\d+\.\d+\.\d+)/) {
print "$1\n";
}
}
每行处理一个IP。如果每行有多个IP,则需要使用/ g选项。 man perlretut 为您提供有关正则表达式的更详细教程。
答案 11 :(得分:0)
以前的所有答案都有一个或多个问题。接受的答案允许IP号码,如999.999.999.999。当前第二个最受欢迎的答案要求前缀为0,例如127.000.000.001或008.008.008.008,而不是127.0.0.1或8.8.8.8。 Apama几乎是正确的,但是这个表达式要求ipnumber是唯一的东西,不允许前导或尾随空间,也不能从行的中间选择ip。
我认为可以在http://www.regextester.com/22
上找到正确的正则表达式因此,如果您想从文件中提取所有ip-adresses,请使用:
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
如果此正则表达式中仍有问题,请评论。很容易找到这个问题的许多错误的正则表达式,我希望这个没有真正的问题。
答案 12 :(得分:0)
这里的每个人都使用非常长篇的正则表达式,但实际上理解POSIX的正则表达式将允许您使用这样的小grep
命令来打印IP地址。
grep -Eo "(([0-9]{1,3})\.){3}([0-9]{1,3})"
(附注) 这不会忽略无效的IP,但它非常简单。
答案 13 :(得分:0)
我已经尝试了所有答案,但所有答案都有一个或多个问题,我列出了一些问题。
123.456.789.111
视为有效IP 127.0.00.1
视为有效的IP 08.8.8.8
所以在这里我发布一个适用于所有上述条件的正则表达式。
注意:我已经提取了超过2百万个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)
答案 14 :(得分:0)
对于那些想要从apache日志中获取IP地址并列出IP地址访问网站的次数的现成解决方案的人,请使用以下行:
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
和一个空格答案 15 :(得分:-1)
如果没有给出特定文件并且您需要提取IP地址,那么我们需要递归执行。 grep命令 - &gt;搜索文本或文件以匹配给定字符串并显示匹配的字符串。
grep -roE&#39; [0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}。[0-9] {1 ,3}&#39; | grep -oE&#39; [0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3}。[0-9] {1,3} &#39;
-r - &gt;我们可以搜索整个目录树,即当前目录和所有级别的子目录。它表示递归搜索。
-o - &gt;仅打印匹配的字符串
-E - &gt;使用扩展正则表达式
如果我们在管道之后没有使用第二个grep命令,我们就会得到IP地址及其存在的路径
答案 16 :(得分:-1)
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地址的位置在开头,结尾和中间某处
第一个regexp在行的开头查找ip地址的完全匹配。 在中间或者在中间查找ip地址之后的第二个正则表达式。我们正在匹配它,使得后面的数字应该恰好是1到3位。在这里可以排除12345.12.34.1之类的错误ips。
第三个正则表达式在行尾查找IP地址
答案 17 :(得分:-1)
我只想从目录中的任何文件中获取以“ 10”开头的IP地址:
grep -o -nr "[10]\{2\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" /var/www
答案 18 :(得分:-2)
for centos6.3
ifconfig eth0 | grep 'inet addr' | awk '{print $2}' | awk 'BEGIN {FS=":"} {print $2}'