我正在写一个Perl脚本,但我没有得到它的一部分。
有一个带主机名的文本文件,每行一个。
我需要搜索第二个带有主机名(黑名单)的文件,以便从第一个文件中读取主机名。要成为圣人,搜索应该是不区分大小写的。
我的第一种方法是使用Perl grep
,但我读到了它,它似乎不太适用于我需要的东西。所以我考虑使用shell grep
。
据我所知,可以使用system
,qx
,反引号和open
来执行。
我决定使用system
,这样我就可以获得grep
的退出状态代码并在if
语句中使用它来完成脚本的其余工作打算。我的代码看起来像这样(带有grep
的测试脚本):
use strict;
use warnings;
my $blacklist_server = "de9899svc";
my $server = undef;
my $exit_value = undef;
open(SERVERLISTE,"/home/ansible/serverscan/scan_results/serverliste_22.02.17.txt") or die "$!";
OUTER: while (<SERVERLISTE>) {
$server = $_;
system("grep -i '\$server' /home/ansible/serverscan/black.list");
$exit_value = $? >> 8;
print "$exit_value\n";
}
close SERVERLISTE;
问题是,无论主机名是否匹配,$exit_value
始终为1。那么有人可以告诉我我错过了什么:)
答案 0 :(得分:4)
更好的问题是询问如何让Perl的grep
做你想做的事。编写Perl代码几乎总是更好的路径,而不是创建一个全新的shell进程来做这样简单的事情。我确信这是可能的,但如果你不解释,我无法纠正你的误解
问题是您不使用chomp
从您从任一文件中读取的记录中删除行结尾。将换行符放在shell命令的中间将在该点终止命令,因此它看起来像grep -i '$server
我会构建一个黑名单服务器的哈希值,并检查列表中的每个服务器
代码看起来像这样。它使用case fc
运算符来比较不区分大小写,因此需要启用该功能
use strict;
use warnings 'all';
use feature qw/ fc say /;
use constant {
SERVER_LISTE => '/home/ansible/serverscan/scan_results/serverliste_22.02.17.txt',
BLACK_LISTE => '/home/ansible/serverscan/black.list',
};
my %blacklist = do {
open my $fh, '<', BLACK_LISTE or die $!;
my @blacklist = <$fh>;
chomp @blacklist;
map { fc $_ => 1 } @blacklist;
};
open my $server_liste, '<', SERVER_LISTE or die $!;
while ( my $server = <$server_liste> ) {
chomp $server;
say "server $server is blacklisted" if $blacklist{ fc $server };
}
答案 1 :(得分:0)
我在你的代码中看到2个问题:$ server包含一个尾随的“\ n”。你应该扼杀它。在调用grep时,你在$。之前有一个\。
答案 2 :(得分:0)
grep -iF -f blacklist serverlist
以上命令打印serverlist
中与blacklist
不敏感的任何行匹配的所有行。
如果您要删除serverlist
中与blacklist
中的任何一行匹配的行,请使用:
grep -viF -f blacklist serverlist
你可以使用后退标记来获取perl内部的输出。
$not_blacklisted=`grep -viF -f blacklist serverlist`;
更易读的命令:
grep --ignore-case --fixed-strings --file=blacklist serverlist
或
grep --invert-match --ignore-case --fixed-strings --file=blacklist serverlist
我尝试使用GNU grep 2.25。