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 )
我一直在构建一个脚本来从 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 )