1

我想逐行从 SUB 标记中提取数据并将数据存储在哈希中。我这样做了,但我没有得到结果

==文件==

<SUB>
 name1="abc"
 value1="24"
 value2="24"
</SUB>

<SUB>
 name="abc2"
</SUB>

<SUB>
 name3="ag"
 value3="27"
</SUB>

<SUB>
 name4="ljh"
 value4="90"
</SUB>

===代码===

use strict;
 use warnings; 
 open my $fh, '<', 'data_file.txt' or die $!;  

 while (<$fh>) {
    while(m{<SUB>(.*?)<\/SUB>}g){
    print $2,"|";
    }
 }

请帮帮我...

4

3 回答 3

2

这应该这样做:

use strict;
use warnings;

while (my $line = <DATA>) {
    if ($line =~ /<SUB>/ .. $line =~ /<\/SUB>/){
        if ( $line =~ /(\S+?)="([^"]+)"/ ) {
            print $1 . " = " . $2 . "\n";
        }
    }
}

__DATA__
<SUB>
 name1="abc"
 value1="24"
 value2="24"
</SUB>

<SUB>
 name="abc2"
</SUB>

<SUB>
 name3="ag"
 value3="27"
</SUB>

<SUB>
 name4="ljh"
 value4="90"
</SUB>

如果您无法理解我的代码,请询问。

于 2012-08-17T07:54:16.093 回答
0

while (<$fh>)构造一次只能在线读取…… 并且当仅存在一个捕获组时,您使用捕获缓冲区 2 $2……您没有收到有关字符串或连接中未定义变量 $2 的警告吗?

有几种解决方案:

  1. 将整个文件读入一个字符串:

    my $fileContents = do {
       local $/ = undef; # input line seperator, undef means "slurp"
       join "", <$fh>;
    };
    while(/(...)/g) {...}
    
  2. 使用触发器 ( ..) 运算符确定我们是否在标签内。仅当每个标签各自占据一行时才按需要工作。请参阅@taulis 优秀的代码答案。

  3. 额外的漂亮:将输入分隔符设置为结束标记:每次执行一行读取时,都会读取直到遇到结束标记(包括在内)。

    local $/ = "\n</SUB>\n";
    while (my $entry = <$fh>) {
         # only keep what's inside the tag
         $line =~ s{ <SUB> \s* (.*?) \s* </SUB> $}{$1}sx;
         # do further processing like printing
    }
    
于 2012-08-17T08:01:29.583 回答
0
{
local $/;
#slurp mode read whole file in
<>;
print join "|", m{<SUB>(.*?)<\/SUB>}sg;
}

1)您需要阅读整个文件,而不是逐行阅读 2)添加 /s 以便点 (.) 匹配换行符。

于 2012-08-17T08:00:16.430 回答