3

我的文本文件:

Name: mak
Place: ynr
Age: 22
------------- 
Name: john
Place: kkr
Age: 21
------------- 
Name: mak
Place: knl
Age: 23
-------------

我正在做的是:

open(FILE, "path to file") or die "";
$check="mak";
@arr=<FILE>
for(@arr)
{
    if ($_=/Name:\s(.*)/)
    {
        $a=$1;
        if($a eq $check)
        {
            print "matched name"
        }
        #now i want if "mak" is matched then after that it should match the age and store it one variable and then compare it with other matched age with same name
    }
}

我想先得到名字,如果它匹配为“mak”,那么我还需要检查年龄并比较年龄。

4

3 回答 3

4

您的文件格式可以描述如下:

  • 多条记录由水平条相互分隔
  • 每条记录都有多个名称-值对,每个在自己的行上

输入记录分隔符$/可以设置为任意字符串,所以我们可以

local $/ = "-------------\n";

现在,每个 readline 操作都将返回一条记录。chomp将删除分隔符。

从记录中获取字段非常简单

my %fields = map split(/:\s*/, $_, 2), split /\n/, $record;

我们可以结合它来一次检查一条记录:

use strict; use warnings;

my $check = shift @ARGV;

local $/ = "-------------\n";
while (<>) {
  chomp;
  my %fields = map split(/:\s*/, $_, 2), split /\n/, $_;
  if ($fields{Name} eq $check) {
    # do something
  }
}

这将在命令行上调用,例如perl the-script.pl mak file.txt.

于 2013-05-01T12:46:32.280 回答
2

有很多方法可以解决这个问题,但我喜欢一种简洁的方法:

use File::Slurp;
@records=split('---',read_file('file.txt'))

现在$records[0],例如,包含:

Name: mak
Place: ynr
Age: 22

因为拆分模式并不完美,所以会有“垃圾”条目@records,但这没关系。现在您可以遍历@records以找到您需要的那个。

于 2013-05-01T12:33:50.930 回答
0

这是另一种选择:

use strict;
use warnings;

my @rec;
while (<>) {
    push @rec, $1 if /^(?:Name|Place|Age):\s+(.+)/;
    next unless @rec == 3;

    print "@rec\n" if $rec[0] eq 'mak' and $rec[2] == 23;

    undef @rec;
}

用法:perl script.pl inFile [>outFile]

最后一个可选参数将输出重定向到文件。

数据集上的输出:

mak knl 23

读取文件行时,正则表达式会查找以 Name、Age 或 Place 开头的行,然后捕获冒号后面的所有空格。将捕获的值$1写入push@rec并读取下一行unless已处理的三个记录行。如果元素 0@rec等于“mak”且元素 2 等于 23,则打印记录的值。最后,@recundefined,所以它为下一个记录做好了准备。

希望这可以帮助!

于 2013-05-01T15:07:13.290 回答