用于解析文本文件并匹配字符串的Perl脚本

时间:2014-06-02 22:00:38

标签: perl

我正在编辑我的问题以添加更多详细信息

脚本执行命令并将输出重定向到文本文件。

然后脚本解析文本文件以匹配以下字符串“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');

4 个答案:

答案 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

我建议这样做,因为从中可以学到两件事:

  1. Perl提供了很好的工具,可以在命令行上进行基本过滤和数据调整。
  2. 有时候,一种更简单的方法可以更好,更快地找到解决方案。
  3. 对于每个可能的数据提取问题,这绝对不是完美的解决方案,但对于这个特定的问题,它正是您所需要的。

    -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