捕获Perl文件中某些行之间的选择数据。

时间:2015-12-28 07:50:53

标签: regex perl file-io

我有一个包含此类内容的文件:

*** X REGION ***
|-------------------------------------------------------------------------------------------------|
| X                                                                                               |                                                                                           
| addr              tag          extra data   |
|-------------------------------------------------------------------------------------------------|
| $A1    label_A1X                   |       1 |
| $A2    label_A2X                   |       2 |
| $A3    label_A3X                   |       3 |

*** Y REGION ***

|-------------------------------------------------------------------------------------------------|
| Y                                                                                            |
| addr              tag           extra data  |
|-------------------------------------------------------------------------------------------------|
| $0     label_0Y                    |        99 |
| $1                                 |        98 |

我需要在' addr'下捕获数据。和'标记&#39 ;;被逗号隔开; 单独以获取' X REGION'下的记录和' Y地区'。 这就是我的尝试:

open($fh1, "<", $memFile) or warn "Cannot open $memFile, $!";            #input file with contents as described above. 

open($fh, "+<", $XFile) or warn "Cannot open $XFile, $!";                
open($fh2, "+<", $YFile) or warn "Cannot open $YFile, $!";               

while(my $line = <$fh1>)
{

  chomp $line;
  $line = $line if (/\s+\*\*\*\s+X REGION\s+\*\*\*/ .. /\s+\*\*\*\s+Y REGION\s+\*\*\*/);        #Trying to get at the stuff in the X region.
  if($line =~ /\s+|\s+\$(.*)\s+(.*)\s+|(.*)/) 
  {
    $line = "$1,$2";
    print $fh $line; 
    print $fh "\n";
  }

  my $lastLineNum = `tail -1 filename`;
  $line = $line if (/\*\*\* Y REGION \*\*\*/ .. $lastLineNum);                      #Trying to get at the stuff in the Y region.
  if($line =~ /\s+|\s+\$(.*)\s+(.*)\s+|(.*)/)
  {
    $line = "$1,$2";
    print $fh2 $line;
    print $fh2 "\n";
  }

}

这表示$ 1和$ 2未初始化。正则表达式是不正确的?还有(还有)还有什么?

1 个答案:

答案 0 :(得分:3)

这是一段代码,可以根据需要运行(充分利用默认的perl隐式var $_):

# use die instead of warn, don't go ahead if there is no file
open(my $fin, "<", $memFile) or die "Cannot open $memFile, $!"; 

while(<$fin>)
{
    # Flip flop between X and Y regions
    if (/[*]{3}\h+X REGION\h+[*]{3}/../[*]{3}\h+Y REGION\h+[*]{3}/) {
        print "X: $1,$2\n" if (/.*\$(\S*)\h*(\S*)\h*[|]/)
    }

    # Flip flop from Y till the end, using undef no need of external tail
    if (/[*]{3}\h+Y REGION\h+[*]{3}/..undef) {
        print "Y: $1,$2\n" if (/.*\$(\S*)\h*(\S*)\h*[|]/)
    }
}

这是输出:

X: A1,label_A1X
X: A2,label_A2X
X: A3,label_A3X
Y: 0,label_0Y
Y: 1,

Online running demo

谈论你的代码有很多要解决的问题:

  • 在你的正则表达式中选择管道|需要转义的分隔符之间的元素:使用反斜杠\|或char类[|](我更喜欢后者)< / p>

  • \s也匹配换行符(严格\n或回车\r),不要将其用作一般空格加标签\t替换。使用\h(仅限水平空格)代替

  • 您使用\s+启动正则表达式,但在示例中,表格行的第一个字符始终为'|'

  • .*除了换行符(\n\r

  • 之外还匹配任何内容(包括空格)
  • 所以像.*\s+这样的正则表达式匹配整行和新行(\s)以及下一行中可能的空格

  • 触发器perl运算符..为您提供所选区域(包括边缘)中的行,但每次一行,因此转义的管道表单也是如此你的正则表达式:

    \s+[|]\s+\$(.*)\s+(.*)\s+[|](.*)

    根本无法匹配see as it behaves on the text

所以我用这个替换了数据提取正则表达式:

.*\$(\S*)\h*(\S*)\h*[|]

正则表达式突破

.*\$     # matches all till a literal dollar '$'
(\S*)    # Capturing group $1, matches zero or more non-space char [^\s]
         # can be replaced with (\w*) if your labels matches [0-9a-zA-Z_]
\h*      # Match zero or more horizontal spaces 
(\S*)    # Capturing group $2, as above
\h*      # Match zero or more horizontal spaces 
[|]      # Match a literal pipe '|'