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

Perl - Capture and Substitute Multiple Matches in an If Statement

我一直在构建一个脚本来从 IBM 的 SPSS Statistics 包中获取一些输出并将其转换为 SPSS 输入语法。我目前遇到以下问题,我似乎无法弄清楚。我有一些文本如下所示:

VALUE LABELS V10
-1
 1 "Yes".

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

我想用标有“-9 "Missing"”的标签替换引号中未跟有标签且没有 space 缩进的负值,并且然后我想在散列中捕获这些负值中的每一个以及变量名(即 V10、V11),以便稍后在重新编码语句中打印它们。我正在通过 perl 读取此文件,将 "lines" 拆分为文字句点后跟一个新行(表示 SPSS 中的命令结束)。但是,到目前为止我提出的代码只是替换和捕获每个 "line" 的一个负值匹配,我不确定我做错了什么。我当前的代码如下所示:

my %negmiss;
my @lines = split(/(\.\n)/,$_);
foreach my $line (@lines) {
    my $modline = $line;
    if ($line =~ /VALUE LABELS\s(\S+)/g) {
       my $label_name = ;
       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}}, ;
       }
    }
print $modline;
}
foreach (@negname) {
    print "RECODE $_ (@{ $negmiss{$_} } = -9\.\n";
}

它部分有效,但同样,它只是为每个 "lines" 替换和捕获一个负值,所以我的输出如下所示:

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 "line"?

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

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).

问题的根源在这里:

/\n(-\d+(\.\d+)?)\n/\n -9 \"Missing\"\n/g;

因为你的前缀 后缀你的模式 \n 这意味着你的 second "\n" 被上一场比赛 - 所以它不会匹配两次。

将其更改为

/\n(-\d+(\.\d+)?)(?=\n)/\n -9 \"Missing\"\n/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' 行:

       push my @negname, $label_name;

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

$/ 设置为 '' 将在 "paragraph mode" 中工作 - 空行分隔。

也许是这样的?:

#!/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".

这给出了输出:

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 )