Perl:从文件中的每一行抓取第n个和第m个分隔的单词

时间:2008-10-01 02:34:20

标签: regex perl file-io

由于在Nagios中添加要监控的主机的方式比较繁琐(需要定义主机对象,而不是以前只需要IP和主机名的程序),我认为最好自动执行此操作,这是学习Perl的好时机,因为我目前所知的只有C / C ++和Java。

我读的文件如下所示:

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

我想要的只是前2个角色。这些显然是空间划界的,但为了一般性,它也可能是任何东西。为了使它更通用,为什么不是第一个和第三个,或第四个和第十个?当然必须有一些正则表达式的行动,但我暂时不会留下那个标签,以防万一。

7 个答案:

答案 0 :(得分:8)

如果您没有编写更多Perl来处理结果,那么单行很棒。

更一般地说,在更大的Perl程序的上下文中,您可以编写自定义正则表达式,例如:

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

...或者您将使用拆分运算符。

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

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

答案 1 :(得分:7)

让我们把它变成代码高尔夫吧!基于大卫的优秀答案,这是我的:

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

编辑:真正的高尔夫提交看起来更像是这样(刮掉五招):

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

但是这个问题的目的不太可读。 :-P

答案 2 :(得分:7)

这是一个通用解决方案(如果我们稍微离开代码高尔夫球)。

#!/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];

当然,如果您正在解析以冒号分隔的文件,那么这些文件没有注释也很好,您也不必剥离它们。

答案 3 :(得分:6)

简单的单行是

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

您可以使用-F

更改分隔符

答案 4 :(得分:4)

大卫尼姆说:

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)联机帮助页。

答案 5 :(得分:0)

由于雷问道,我以为我会在没有使用Perl的隐含性的情况下重写我的整个程序(除了使用<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+/是相似的,除了如何处理行开头的空格。所以{ {1}}真的很神奇。)

故事的寓意是,如果你喜欢很多神奇的行为,Perl会很棒。如果你没有它,请使用Python。 :-P

答案 6 :(得分:0)

在行号L中找到第N到第M个字符---查找标签的示例


@echo off

REM Next line = Set command value to a file  OR  Just Choose Your File By Skipping The Line
vol E: > %temp%\justtmp.txt
REM  Vol E:  = Find Volume Lable Of Drive E

REM  Next Line to choose line line no. +0 = line no. 1 
for /f "usebackq delims=" %%a in (`more +0 %temp%\justtmp.txt`) DO (set findstringline=%%a& goto :nextstep)

:nextstep

REM  Next line to read nth to mth Character  here 22th Character to 40th Character
set result=%findstringline:~22,40%

echo %result%
pause
exit /b

另存为查找label.cmd

结果将是您的驱动器E标签

享受