Perl:从文件中的每一行抓取第n和第m个定界字

时间:2020-03-06 14:57:32  来源:igfitidea点击:

由于在Nagios中添加要监视的主机的方法比较繁琐(与以前的程序仅需要IP和主机名相对,它需要定义一个主机对象,而以前的程序则需要定义一个主机对象),所以我认为最好自动执行此操作,并且这将是学习Perl的好时机,因为目前我所知道的只是C / C ++和Java。

我从中读取的文件如下所示:

xxx.xxx.xxx.xxx hostname #comments. i.dont. care. about

我想要的只是前2个字符。这些显然是用空格分隔的,但是为了通用起见,它也可能是任何东西。为了使它更笼统,为什么不选择第一和第三,或者第四和第十?当然,必须涉及到一些正则表达式操作,但是为了以防万一,我暂时暂时不使用该标签。

解决方案

一个简单的单线是

perl -nae 'print "$F[0] $F[1]\n";'

我们可以使用-F更改定界符

让我们把它变成代码高尔夫!根据David的出色回答,这是我的:

perl -ane 'print "@F[0,1]\n";'

编辑:真正的高尔夫投稿看起来更像这样(取消了五招):

perl -ape '$_="@F[0,1]
"'

但这对于这个问题的目的来说不太容易理解。 :-P

大卫·内姆(David Nehme)说:

perl -nae 'print "$F[0] $F[1}\n";

它使用-a开关。我必须查一查:

-a   turns on autosplit mode when used with a -n or -p.  An implicit split
     command to the @F array is done as the first thing inside the implicit
     while loop produced by the -n or -p.

你每天都学到一些东西。 -n导致将每一行传递给

LINE:
    while (<>) {
        ...             # your program goes here
    }

最后,-e是一种直接输入程序单行的方法。我们可以拥有多个-e。其中大部分是perlrun(1)联机帮助页的一部分。

这是一个通用的解决方案(如果我们稍微远离代码编程的话)。

#!/usr/bin/perl -n
chop;                     # strip newline (in case next line doesn't strip it)
s/#.*//;                  # strip comments
next unless /\S/;         # don't process line if it has nothing (left)
@fields = (split)[0,1];   # split line, and get wanted fields
print join(' ', @fields), "\n";

通常split按空格分割。如果那不是我们想要的(例如,解析/ etc / passwd),则可以将定界符作为正则表达式传递:

@fields = (split /:/)[0,2,4..6];

当然,如果我们要分析用冒号分隔的文件,则很有可能此类文件没有注释,也不必剥离它们。

如果我们不编写更多的Perl来处理结果,那么单行代码就很棒。

不过,更一般而言,在较大的Perl程序的上下文中,我们可以编写一个自定义的正则表达式,例如:

if($line =~ m/(\S+)\s+(\S+)/) {
     $ip = ;
     $hostname = ;
}

...或者我们将使用split运算符。

my @arr = split(/ /, $line);
$ip = $arr[0];
$hostname = $arr[1];

无论哪种方式,都添加逻辑以检查无效输入。

自从ray问到之后,我以为我会在不使用Perl隐式性的情况下重写整个程序(除非使用&lt;ARGV>;这很难手动写出)。这可能会使Python的人更快乐(尽管括号为:-P):

while (my $line = <ARGV>) {
    chop $line;
    $line =~ s/#.*//;
    next unless $line =~ /\S/;
    @fields = (split ' ', $line)[0,1];
    print join(' ', @fields), "\n";
}

我有什么想念的吗?希望不会。 " ARGV"文件句柄是特殊的。除非指定了没有指定的名称,否则它将导致读取命令行上的每个命名文件,在这种情况下,它将读取标准输入。

编辑:哦,我忘了。与split / /不同,split''也很神奇。后者仅与一个空格匹配。前者匹配任何数量的空白。如果没有为split指定模式,则默认使用这种神奇的行为。 (有人会说,但是/ \ s + /''/ \ s + /相似,除了如何处理行首的空白。所以'''`确实是神奇的)

这个故事的寓意是,如果我们喜欢许多神奇的行为,Perl就是很棒的选择。如果没有它,请使用Python。 :-P