Perl - 在If语句中捕获和替换多个匹配项

时间:2017-04-13 14:35:16

标签: regex perl pcre regex-group

我一直在构建一个脚本来从IBM的SPSS Statistics包中获取一些输出并将其转换为SPSS输入语法。我目前遇到的问题似乎无法解决。我有一些看起来如下的文字:

VALUE LABELS V10
-1
 1 "Yes".

VALUE LABELS V11
-50.00
-33.33
 -10 "Don't Know".

我想替换引号中没有后跟标签的负值,并且没有带有标记为“-9”缺少“'的空格缩进,然后我想要捕获其中的每一个散列中的负值以及变量名称(即V10,V11),以便稍后我可以在重新编码语句中打印它们。我正在通过perl读取此文件,将“行”除以文字句点后跟一个新行(表示SPSS中命令的结束)。但是,到目前为止我提出的代码只是替换并捕获每个“行”的一个负值匹配,我不确定我做错了什么。我目前的代码如下:

my %negmiss;
my @lines = split(/(\.\n)/,$_);
foreach my $line (@lines) {
    my $modline = $line;
    if ($line =~ /VALUE LABELS\s(\S+)/g) {
       my $label_name = $1;
       if ($line =~ /\n(-\d+(\.\d+)?)\n/g) {
           $modline =~ /\n(-\d+(\.\d+)?)\n/\n -9 \"Missing\"\n/g;
           push my @negname, $label_name;
           push @{$negmiss{$label_name}}, $1;
       }
    }
print $modline;
}
foreach (@negname) {
    print "RECODE $_ (@{ $negmiss{$_} } = -9\.\n";
}

它部分有效,但同样,它只替换并捕获每个“行”的一个负值,所以我的输出看起来像这样:

VALUE LABELS V10
 -9 "Missing"
 1 "Yes".

VALUE LABELS V11
 -9 "Missing"
-33.33
 -10 "Don't Know".

RECODE V10 (-1 = -9).
RECODE V11 (-50.00 = -9).

如何捕获并替换V11“线”的-50.00和-33.33?

编辑:我希望我的输出看起来像这样:

VALUE LABELS V10
 -9 "Missing"
 1 "Yes".

VALUE LABELS V11
 -9 "Missing"
 -9 "Missing"
 -10 "Don't Know".

RECODE V10 (-1 = -9).
RECODE V11 (-50.00 = -9).
RECODE V11 (-33.33 = -9).

1 个答案:

答案 0 :(得分:0)

问题的根源在于:

Serializable

因为你的模式前缀为后缀为/\n(-\d+(\.\d+)?)\n/\n -9 \"Missing\"\n/g; ,这意味着你的第二个“\ n”被前一个匹配所消耗 - 所以它不会匹配两次。

将其更改为

\n

(或者可能更好/\n(-\d+(\.\d+)?)(?=\n)/\n -9 \"Missing\"\n/g; ),它应该没问题。

E.g:

$

你的'推'线:

#!/usr/bin/env perl

use strict;
use warnings;

local $/ = '';

while ( <DATA> ) {
   s/\n(-\d+(\.\d+)?)(?=\n)/\n -9 \"Missing\"/g;
   print;
}

__DATA__
VALUE LABELS V10
-1
 1 "Yes".

VALUE LABELS V11
-50.00
-33.33
 -10 "Don't Know".

虽然不会做太多 - 最好不要这样做。我还建议你设置记录分隔符,因为这意味着你可以按记录工作。

设置为 push my @negname, $label_name;

$/将在“段落模式”下工作 - 空白行分隔。

也许是这样的?:

''

这给出了输出:

#!/usr/bin/env perl

use strict;
use warnings;

my %recode; 

local $/ = '';

while ( <DATA> ) {
   my ( $label_name ) = m/VALUE LABELS (\S+)/;
   my @recode = m/^\s*(\-[\d\.]+)$/gm;
   $recode{$label_name} = \@recode;

   s/\n(-\d+(\.\d+)?)(?=\n)/\n -9 \"Missing\"/g;
   print;
}

print "\n\n";

foreach my $key ( sort keys %recode ) {
   foreach my $value ( @{$recode{$key}} ) {
     print "RECODE $key ( $value = -9 )\n";
   }
}

__DATA__
VALUE LABELS V10
-1
 1 "Yes".

VALUE LABELS V11
-50.00
-33.33
 -10 "Don't Know".