我该如何使这个Perl正则表达式生效?

4

我有这行代码

/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"

我想提取.\main.cpp文件。我认为以下方法可以解决问题:

if($string =~ /.*\s+(.*)$/i) {
 print "matched ",$1,"\n";
}

因为这个相同的正则表达式在Ruby中有效,并提取了我需要的字符串。我该如何让它工作?
编辑:这是我设置字符串的方式:
for(find_indexes(\@lines,"/MDd")) {
    my $actual_line = $lines[$_];
    $actual_line    = modify($actual_line,$additional_defs);
}

find_indexes函数返回与数组引用后的任何参数匹配的行的索引。 modify子程序将返回一个修改后的字符串版本,其中包含一些附加定义。

编辑2:这是modify子程序:

sub modify {
    my $string      = shift;
    chomp($string);
    my @defines     = @_;
    if($string =~ /.*\s+(\".*?)$/) {
        my $match = $1;
        print "match is $match";
        my $string_copy = $string;
        print "|$string_copy|\n";
    }
}

这个子程序并不完整,因为我没能让它按照应该的方式工作。我在捕获组中添加了一个额外的引号来强制匹配名称。但是发生了一些奇怪的事情,我希望$string_copy的输出会打印出被|包围的原始字符串。然而,我只得到了前导管道符,而没有结尾的那个。我想也许是Perl错误地解释了内插变量,我试图像这样做:

print "|",$string_copy,"|\n";

但是我仍然只得到一个前导管道符。这让我想到字符串可能确实存在问题。我想不出其他原因。


输出的结果为 "匹配"。 - Geo
4个回答

2
my $string = '/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"';
if($string =~ /.*\s+(.*)$/i) {
    print "matched ",$1,"\n";
}

这对我有用,并打印出matched .\main.cpp

请展示如何设置$string。可能是你在引号或其他方面弄错了。

编辑:你的字符串末尾可能有\x0d符号吗?当你打印字符串并且chomp无法移除它时,你不会注意到它:

my $string = '/Od /D "WIN32" /D "_DEBUG" /FD /EHa /MDd /Fo"Debug" /Fd"Debug\vc80.pdb" /W3 /c /Zi /clr /TP .\main.cpp"' . "\x0d";
chomp $string;
if($string =~ /.*\s+(.*)$/i) {
    print "matched ",$1,"\n";
}

这段代码会输出matched,但不会捕获文件名。也许你的情况就是这样?

C:\>perl --version

This is perl, v5.10.1 built for MSWin32-x64-multi-thread

OP说他正在从文件中导入字符串。我现在能够复现他的问题。 - sholsapp
这只是一个例子。例如,如果文件使用Windows的换行符(\x0d\x0a)编写,并且有一个认为换行符是\x0a的Cygwin Perl,那么字符串末尾会有\x0d,正则表达式将无法匹配。 - Paul
版本是 This is perl, v5.10.1 built for MSWin32-x86-multi-thread\x0d 对字符串有什么影响? - Geo
你可以尝试这个: $string =~ s/[\x0a\x0d]//g; - Paul
1
你也可以尝试在chomp之前添加以下内容:local $/ = "\r\n"; - pioto
显示剩余3条评论

2

前导的 .* 是无意义的,同样 /i 修饰符也是。

如果字符串以换行符结尾,则会被 \s+ 匹配。由于随后的 (.*) 可以匹配空,因此匹配将成功,但 $1 将为空。相反,强制它匹配某些内容:/(\S+)"$/


在我尝试匹配它之前,该字符串已被修剪。 - Geo

1

看起来你实际上想要的是

$string =~ /(\S+)$/

0

试试这个:

#!/usr/bin/perl

$string = <STDIN>;
chomp($string);
print $string;

if($string =~ /.*\s+(.*)$/) {
  print "\nmatched ",$1,"\n";
}

这是 Perl,v5.8.8 版本,适用于 i486-linux-gnu-thread-multi 架构


它与字符串不匹配。我得到了相同的输出。 - Geo
你传递字符串的方式可能有问题。你能给我们展示一下你使用的确切命令吗? - sholsapp
我正在从文件中读取字符串。它应该自动转义,对吗? - Geo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接