我一直在尝试读取名为“perlthisfile.txt”的文件,该文件基本上是我计算机上nmap的输出。
我想只打印出的ip地址,所以我写了下面的代码,但它不起作用:
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw(looks_like_number);
print"\n running \n";
open (MYFILE, 'perlthisfile.txt') or die "Cannot open file\n";
while(<MYFILE>) {
chomp;
my @value = split(' ', <MYFILE>);
print"\n before foreach \n";
foreach my $val (@value) {
if (looks_like_number($val)) {
print "\n looks like number block \n";
if ($val == /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5})/) {
print "\n$val\n";
}
}
}
}
close(MYFILE);
exit 0;
当我运行此代码时输出为:
running
before foreach
before foreach
looks like number block
before foreach
looks like number block
before foreach
looks like number block
我的perlthisfile.txt:
Starting Nmap 6.00 ( http://nmap.org ) at 2013-10-16 22:59 EST
Nmap scan report for BoB2.iiNet (10.1.1.1)
Nmap scan report for android-fbff3c3812154cdc (10.1.1.3)
All 1000 scanned ports on android-fbff3c3812154cdc (10.1.1.3) are closed
Nmap scan report for 10.1.1.5
All 1000 scanned ports on 10.1.1.5 are open|filtered
Nmap scan report for 10.1.1.6
All 1000 scanned ports on 10.1.1.6 are closed
答案 0 :(得分:3)
这里有几个问题。正如@toolic所说,在<MYFILE>
内调用split
可能不是您想要的 - 它会从文件中读取下一条记录,而是使用$_
。
此外,您正在使用带有正则表达式的==
,您应该使用绑定运算符=~
(==
仅用于Perl中的 numeric 比较):
if ($val =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5})/){
如果正则表达式有效,我建议looks_like_number
是多余的。我怀疑你使用它是因为==
提供的内容类似isn't numeric in numeric eq (==)
,具体取决于您使用的perl版本。
答案 1 :(得分:2)
你有一些错误,其中一个是正则表达式,它应该有端口号的可选部分(:
和\d{1,5}
之后)
#!/usr/bin/perl
use strict;
use warnings;
open (my $MYFILE, '<', 'perlthisfile.txt') or die $!;
my $looks_like_ip = qr/( \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} (?: : \d{1,5})? )/x;
while (<$MYFILE>) {
chomp;
my @value = split;
print"\n before foreach \n";
foreach my $val (@value) {
if (my ($match) = $val =~ /$looks_like_ip/){
print "\n$match\n";
}
# else { print "$val doesn't contain IP\n" }
}
}
close($MYFILE) or warn $!;
答案 2 :(得分:2)
如果这看起来像是一个快速破解提取IP的东西,你可能会侥幸逃脱:
perl -nlwe '/((?:\d+\.)+\d+)/ && print $1' perlthisfile.txt
也就是说,不是一个非常严格的正则表达式,它只是匹配由句点连接的数字。如果您只想打印唯一的IP,可以使用哈希值进行重复数据删除:
perl -nlwe '/((?:\d+\.)+\d+)/ && !$seen{$1}++ && print $1" perlthisfile.txt
稍微紧凑的正则表达式也匹配端口号:
perl -nlwe '/((?:\d+[\.:]){3,4}\d+)/ && print $1' perlthisfile.txt
这将禁止更短的数字链,并允许端口号。
最后一个正则表达式解释说:
/( # opening parenthesis, starts a string capture
(?: # a non-capturing parenthesis
\d+ # match a number, repeated one or more times
[\.:] # [ ... ] is a character class, it matches one of the literal
# characters inside it, and only one time
){3,4} # closing the non-capturing parenthesis, adding a quantifier
# that says this parenthesis can match 3 or 4 times
\d+ # match one or more numbers
)/x # close capturing parenthesis (added `/x` switch)
/x
开关只是为了你可以使用上面的正则表达式,带有注释和空格。
这背后的逻辑很简单:我们想要一个由数字后跟句点或冒号组成的字符串。我们想要这个字符串3或4次。以另一个号码结束。
+
和{3,4}
是量词,它们决定了左边项目应该匹配多少次。默认情况下,每个项目都匹配一次,但通过使用量词,您可以更改它。 +
是{1,}
的简写,您还有:
? -> {1,0}
* -> {0,}
语法为{min,max}
,当缺少数字时,这意味着尽可能多的次数。