我正在编辑我的问题以添加更多详细信息
脚本执行命令并将输出重定向到文本文件。
然后脚本解析文本文件以匹配以下字符串“Standard 1.1.1.1”
文本文件中的输出是:
Host Configuration
------------------
Profile Hostname
-------- ---------
standard 1.1.1.1
standard 1.1.1.2
如果我搜索1.1.1.1或标准,代码可以正常工作。当我一起搜索标准1.1.1.1时,以下脚本失败。
这是我得到的错误“无法找到字符串:testtest.pl上的标准172.25.44.241
#!/usr/bin/perl
use Net::SSH::Expect;
use strict;
use warnings;
use autodie;
open (HOSTRULES, ">hostrules.txt") || die "could not open output file";
my $hos = $ssh->exec(" I typed the command here ");
print HOSTRULES ($hos);
close(HOSTRULES);
sub find_string
{
my ($file, $string) = @_;
open my $fh, '<', $file;
while (<$fh>) {
return 1 if /\Q$string/;
}
die "Unable to find string: $string";
}
find_string('hostrules.txt', 'standard 1.1.1.1');
答案 0 :(得分:2)
也许写一个函数:
use strict;
use warnings;
use autodie;
sub find_string {
my ($file, $string) = @_;
open my $fh, '<', $file;
while (<$fh>) {
return 1 if /\Q$string/;
}
die "Unable to find string: $string";
}
find_string('output.txt', 'object-cache enabled');
或者只是啜饮整个文件:
use strict;
use warnings;
use autodie;
my $data = do {
open my $fh, '<', 'output.txt';
local $/;
<$fh>;
};
die "Unable to find string" if $data !~ /object-cache enabled/;
答案 1 :(得分:0)
perl -ne '/object-cache enabled/ and $found++; END{ print "Object cache disabled\n" unless $found}' < input_file
这只是一次读取一行文件;如果我们找到关键短语,我们会增加$found
。最后,在我们阅读完整个文件后,除非找到短语,否则我们会打印该消息。
如果邮件不足,您可以改为exit 1 unless $found
。
我建议这样做,因为从中可以学到两件事:
对于每个可能的数据提取问题,这绝对不是完美的解决方案,但对于这个特定的问题,它正是您所需要的。
-ne
选项标志告诉Perl设置一个while
循环来一次读取一行的所有标准输入,并获取跟随它的任何代码并将其运行到其中间循环,导致'在一个命令行中'在文件'程序中的每一行上运行此模式匹配。
END
块可以在任何地方出现,并且始终只在程序结束时运行,因此在while
生成的-n
循环内定义它是完全正常的。当程序用完行时,我们会掉出while
循环的底部并耗尽程序,因此Perl结束程序,触发执行END块以打印(或不打印)警告。 / p>
如果您搜索的文件包含一个表示缓存已被禁用的字符串(您要捕获的条件),则可能更短:
perl -ne '/object-cache disabled/ and die "Object cache disabled\n"' < input_file
程序只扫描文件,直到看到缓存被禁用的指示,并在此时异常退出。
答案 2 :(得分:0)
您正在扫描文件以查找特定字符串。如果该字符串中的字符串不,则需要抛出错误。听起来像是grep的工作。
use strict;
use warnings;
use features qw(say);
use autodie;
use constant {
OUTPUT_FILE => 'output.txt',
NEEDED_STRING => "object-cache enabled",
};
open my $out_fh, "<", OUTPUT_FILE;
my @output_lines = <$out_fh>;
close $out_fh;
chomp @output_lines;
grep { /@{[NEEDED_STRING]}/ } @output_lines or
die qq(ERROR! ERROR! ERROR!); #Or whatever you want
die
命令将结束程序并以非零退出代码退出。该错误将打印在STDERR上。
我不知道原因,但使用qr(object-cache enabled),
然后使用grep { NEEDED_STRING }
似乎无效。使用@{[...]}
可以插入常量。
您可能希望能够使用GetOptions传递错误字符串和文件名,而不是常量。
我使用旧时尚<...>
文件处理而不是IO::File
,但那是因为我是一个古老的模范者,他在20世纪才知道Perl很酷。您可以使用IO::File
,这可能更好,更现代。
在内存中诋毁整个文件的原因是什么? - 莱昂纳多·埃雷拉
只要文件大小合适(比如100,000行左右),将整个文件读入内存就不会那么糟糕。但是,您可以使用循环:
use strict;
use warnings;
use features qw(say);
use autodie;
use constant {
OUTPUT_FILE => 'output.txt',
NEEDED_STRING => qr(object-cache enabled),
};
open my $out_fh, "<", OUTPUT_FILE;
my $output_string_found; # Flag to see if output string is found
while ( my $line = <$out_fh> ) {
if ( $line =~ NEEDED_STRING ){
$output_string_found = "Yup!"
last; # We found the string. No more looping.
}
}
die qq(ERROR, ERROR, ERROR) unless $output_string_found;
这将使用定义为引用的正则表达式的常量NEEDED_STRING
。
答案 3 :(得分:0)
首先,您为什么使用Net::SSH::Expect
?你在执行远程命令吗?如果没有,那么执行程序并等待其完成所需的只是system
。
system("cmd > file.txt") or die "Couldn't execute: $!";
其次,看来失败的是你的正则表达式。您正在搜索文字表达式standard 1.1.1.1
,但在示例文本中,所需字符串似乎包含制表符或多个空格而不是单个空格。尝试将您的通话更改为find_string
功能:
find_string('hostrules.txt', 'standard\s+1.1.1.1'); # note '\s+' here