从文本文件形成 IP 地址

从文本文件形成 IP 地址

我有一个巨大的文本文件,其中包含各种乱码的 IP 地址,但不在一个单元中

例如。

那么@192@你到底在我家@168@干什么呢?[电子邮件保护]@16@ 不应该在这里。

我想要的是创建一个输出文件,并在其中创建如下所示的 ipadresses 文件

    1.192.168.10.16
    2.192.223.22.44
    etc..

我对正则表达式有很好的理解,可以从文本文件中提取特定信息,但在这里我需要将这些结合起来,这让我感到困惑。应该如何解决这样的问题?我正在使用 Ubuntu 12.04。

答案1

我能想到的最简单的方法是,假设您想要的数字始终由@符号分隔:

$ grep -oP '@\K\d+' file | perl -pe '$. % 4 != 0 && s/\n/./;'
192.168.10.16
192.169.10.16
192.128.10.16
192.162.10.16

不过,这不会对行进行编号,因此要添加它们,请执行以下操作

$ grep -oP '@\K\d+' file | perl -pe '$. % 4 != 0 && s/\n/./;' | perl -pe 's/^/$.. /'
1. 192.168.10.16
2. 192.169.10.16
3. 192.128.10.16
4. 192.162.10.16

解释

  • grep -oP '@\K\d+' file:-o表示“仅打印行的匹配部分”,并-P为 启用 Perl 兼容正则表达式 (PCRE) grep。这让我们可以使用 来\d匹配数字,最重要的是, ,\K这意味着“忘记在我之前匹配的任何内容”。\K让我 grep@\K10并只打印10因为@在 之前\K
  • perl -pe:逐行读取输入文件,将给出的脚本应用-e到每一行,然后打印该行(-p)。
  • '$. % 4 != 0 && s/\n/./;%是个取模运算符,是输入文件的当前行号。此代码将在以下行上$.用换行符 ( \n)替换.不是能被 4 整除。结果是,由于我们给它输入了一个数字列表( 的输出grep),每组 4 个数字将打印在同一行上,因为\n已转换为.
  • perl -pe 's/^/$.. /':只需将当前行号添加到每行的开头。

钢铁司机建议一个非常好的选择:

grep -oP '@\K\d+' file | xargs -n4 printf '%d.%d.%d.%d\n' | cat -n

这让我想到了这个:

printf '%d.%d.%d.%d\n' $(grep -oP '@\K\d+' file ) | cat -n

如果您愿意,您可以用 Perl 完成整个操作并避免使用管道,但我会使用上面的方法。无论如何,始终假设您的数字被 包围@,这也会起作用:

perl -ne 'push @f,(/@(\d+)@/g); 
          END{
            $k=1;
            for($i=0;$i<=$#f;$i+=4){
                print "$k. " . join(".",@f[$i..($i+3)]) . "\n"; $k++}
            }' file

您可以将其直接粘贴到终端中,只需更改file为实际文件名即可。输出如下所示:

1. 192.168.10.16
2. 192.169.10.16
3. 192.128.10.16
4. 192.162.10.16

解释

  • perl -ne:逐行读取输入文件(-n)并应用给出的脚本-e

  • push @f,(/@(\d+)@/g);:将 包围的每个数字保存@为数组的一个元素@f

  • END{}:处理完所有行后执行此操作
  • for($i=0;$i<=$#f;$i+=4){}:遍历数组。由于 IP 有 4 组数字,因此我们以 4 为一跳的方式读取数组。
  • join(".",@f[$i..($i+3)]):这将数组的 4 个元素连接起来.以便打印。
  • $k只是打印 IP 前面的数字。

答案2

使用 GNUsed

您也可以将其用于sed此目的。假设 ipaddress 中的数字存在于@@符号之间。

$ sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' file
192.168.10.16
192.169.10.16
192.128.10.16
192.162.10.16

下面的命令将数字按顺序排列在获取的 IP 地址之前,

$ sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' file | awk '{ print NR". "$0}' 

例子:

$ echo 'So what the@192@ heck are you doing@168@ in my house @[email protected] were not @16@ supposed to be here.' | sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' | awk '{ print NR". "$0}'
1. 192.168.10.16

请稍微解释一下你的代码?

sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' file | awk '{ print NR". "$0}'
|                                                                   |   |                     |
|                                                                   |   |                     |
|<----------------------First part--------------------------------->|   |<-----Second part--->|   

OP 提到,IP 地址在整个文件中都是杂乱无章的(分散的),每个部分都包含在其中@@,每行包含四个@...@部分。因此,他想@@逐行提取其中存在的所有数字,并以 ip 地址格式 ( xxx.xxx.xxx.xxx) 打印出来。

第一部分

sed逐行解析输入文件。

考虑一下我代码中的以下正则表达式以及上面提到的例子。我们必须给出与整行匹配的正则表达式,并且它还包含获取组,以便根据我们的标准获取单词,这样获取的组就可以通过反向引用重新使用。

示例行:

So what the@192@ heck are you doing@168@ in my house @[email protected] were not @16@ supposed to be here.

正则表达式:

.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*

.*

它匹配除换行符之外的任意字符 0 次或更多次。

@\(.*\)@

sed, ()(抓取组)中,这些括号用于抓取字符、单词或数字组。默认情况下,sed 使用基本正则表达式,因此我们必须转义括号才能使抓取功能正常工作。但是,如果您使用带有-r( extended-regex) 标志的 sed,则无需转义。

在我们的例子中是\(.*\),左括号和右括号均被转义。sed 读取整行后,会停止匹配并开始获取符号后的所有字符或数字或任何内容@,直到找到下一个@符号后才停止获取。然后,它将获取的组存储在称为(模式空间)的特殊缓冲区中。以便进一步使用获取的字符。现在 sed 获取第一个符号之间的数字@@(即 .192)。

.*

捕获第一组后,sed开始解析下一个字符并匹配任何内容 0 次或更多次。

@\(.*\)@

取出第二个符号之间的数字@@。(例如 168)

.*

匹配任意一个然后继续。

@\(.*\)@

取出第三部分之间的数字@@。(即10)

.*

匹配任意一个然后继续。

@\(.*\)@

取出第四部分之间的数字@@。(即16)

.*

第四个符号后面可能有或没有字符@@。因此我们必须给出这个.*才能匹配第四 @@部分之后的所有字符。

因此sed获取我们想要的精确数字并将其存储在缓冲区中。

默认格式(语法)为sed

sed 's/regex/replacement/g' file

代码:

sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' file

因此 sed 搜索此正则表达式的匹配项。一旦找到匹配项,它将被替换部分替换。g全局标志有助于用替换部分替换所有出现的正则表达式字符串。( g-global)。

在我们的例子中,正则表达式将匹配第一行,整行将被我们获取的组1, 2, 3,替换4。然后 sed 对所有与我们的正则表达式匹配的行执行此操作。在替换部分,获取的组以 开头\。因此它被称为反向引用。如果我们未能用.(点)分隔组,

\1\2\3\4

输出结果为,

1921681016

所以我们必须用.(点)分隔各组。这样它才会以 IP 地址格式出现。

\1.\2.\3.\4

现在输出将是,

192.168.10.16

第二部分

awk '{ print NR". "$0}'

现在第一行的 sed 输出将是192.168.10.16。此输出将作为第二条命令的输入awk

  • Awk 的NR(记录数)变量存储行或记录号。请注意,的最后一个值NR将是最后一个行号。与 一样sedawk逐行解析输入文件。因此NR第一行的值将是 1,第二行将是,2依此类推。

  • 在 awk 的打印函数中,如果将字符放在双引号内,则会按原样打印该字符。因此它会.在行号(即当前 NR)之后打印。

  • $0按原样打印整行。

因此整个命令的输出将是,

$ sed 's/.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*@\(.*\)@.*/\1.\2.\3.\4/g' file | awk '{ print NR". "$0}'
192.168.10.16
192.169.10.16
192.128.10.16
192.162.10.16

您也可以使用此命令,

sed 's/.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*/\1.\2.\3.\4/g' file

例子:

$ echo 'So what the@192@ heck are you doing@168@ in my house @[email protected] were not @16@ supposed to be here.' | sed 's/.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*@\([0-9]\+\)@.*/\1.\2.\3.\4/g'
192.168.10.16

答案3

可能有一种使用终端执行此操作的奇特方法,但我不知道该怎么做。以下是我使用 Python 执行此操作的方法

将此代码复制到新文件中,将其命名为 whatEverYouWant.py,并将“input.txt”行更改为“yourFileWithIps.txt”

import re

validIpAddressRegex = "^(([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])$";

ips = []
with open('input.txt','r') as f:
    output = f.read()
    ips = re.findall(r'[0-9]+(?:\.[0-9]+){3}', output)

for x in range(1, len(ips) + 1):
    print str(x) + '.' + ips[x-1]

然后从终端导航到你保存 whatEverYouWant.py 的位置并输入

python whatEverYouWant.py

这样就应该输出您想要的内容。

我自己测试的结果

cam@cam-P5E:~/Desktop$ python getips.py
1.192.168.0.1
2.255.255.255.0
3.10.0.0.1
4.192.192.192.192

相关内容