Nas*_*eer 1 regex perl sed text-processing
我有一个巨大的文本文件,其中包含散乱的 IP 地址,但不是在一个单元中
例如。
那么@192@你到底在做什么@168@在我家@10@.你不是@16@应该在这里的。
我想要的是制作一个输出文件,并在其中制作 ipadresses 文件,如下所示
1.192.168.10.16
2.192.223.22.44
etc..
Run Code Online (Sandbox Code Playgroud)
我对正则表达式有很好的理解,可以从文本文件中提取特定信息,但在这里我需要结合这些我感到困惑的地方。应该如何解决这样的问题?我正在使用 Ubuntu 12.04。
我能想到的最简单的方法,假设你想要的数字总是用@符号分隔,是:
$ 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
Run Code Online (Sandbox Code Playgroud)
不过,这不会对行进行编号,因此要添加它们
$ 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
Run Code Online (Sandbox Code Playgroud)
grep -oP '@\K\d+' file:-o表示“仅打印该行的匹配部分”并-P为grep. 这让我们可以使用\d来匹配数字,最重要的是,\K这意味着“忘记你之前匹配过的任何东西”。这\K让我 grep for@\K10并且只打印 the10因为@在\K.perl -pe: 逐行读取输入文件,将 给出的脚本应用-e到每一行,然后打印该行 ( -p)。'$. % 4 != 0 && s/\n/./;:%是模运算符,$.是输入文件的当前行号。该代码将取代换行符charatcer( \n)与.上是线不通过4整除的结果是,因为我们喂养它号码的列表(的输出grep),每组4个数字将在相同的印刷行,因为\n被转换为..perl -pe 's/^/$.. /' : 只需将当前行号添加到每行的开头即可。Steeldriver提出了一个非常好的替代方案:
grep -oP '@\K\d+' file | xargs -n4 printf '%d.%d.%d.%d\n' | cat -n
Run Code Online (Sandbox Code Playgroud)
这让我想到了这个:
printf '%d.%d.%d.%d\n' $(grep -oP '@\K\d+' file ) | cat -n
Run Code Online (Sandbox Code Playgroud)
如果你愿意,你可以在 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
Run Code Online (Sandbox Code Playgroud)
您可以将其直接粘贴到终端中,只需更改file实际文件名即可。输出如下所示:
1. 192.168.10.16
2. 192.169.10.16
3. 192.128.10.16
4. 192.162.10.16
Run Code Online (Sandbox Code Playgroud)
perl -ne: 逐行读取输入文件 ( -n) 并应用-e.
push @f,(/@(\d+)@/g);: 将每个被包围的数字保存@为@f数组的一个元素。
END{} :在处理完所有行后执行此操作for($i=0;$i<=$#f;$i+=4){}: 遍历数组。由于 IP 有 4 组数字,因此我们以四次为单位读取数组。join(".",@f[$i..($i+3)]):这将连接数组的 4 个元素以.进行打印。$k只是打印 IP 前面的数字。