【问题标题】:How can I make this Perl regex work?我怎样才能使这个 Perl 正则表达式工作?
【发布时间】:2010-06-10 17:10:50
【问题描述】:

我有这条线

/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 返回与数组 ref 后面的任何参数匹配的行的索引。 modify 子将返回发送给它的字符串的修改版本,其中包含一些额外的定义。

EDIT2:这是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";

但我仍然只得到一个领先的管道。这让我认为字符串可能确实有问题。我想不出别的了。

【问题讨论】:

  • 输出的“匹配”。

标签: regex perl


【解决方案1】:
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 说他从文件中管道输入字符串。我现在可以重现他的问题了。
  • @gnucom,我只显示一些管道,如 |var|这样我就可以查看字符串是否有多余的字符:)
  • 就是这样。例如,如果文件是用 Windows 行尾 (\x0d\x0a) 编写的,并且 Cygwin Perl 认为行尾是 \x0a,则字符串末尾将有 \x0d,并且正则表达式将不匹配。
  • 版本是This is perl, v5.10.1 built for MSWin32-x86-multi-thread\x0d 对字符串有何影响?
  • 你也可以尝试在你的 chomp 之前添加这个:local $/ = "\r\n";
【解决方案2】:

前导 .* 没有意义,/i 修饰符也是如此。

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

【讨论】:

  • 在我尝试匹配之前,字符串已被压缩。
【解决方案3】:

看起来你实际上想要的只是

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

【讨论】:

    【解决方案4】:

    试试这个:

    #!/usr/bin/perl
    
    $string = <STDIN>;
    chomp($string);
    print $string;
    
    if($string =~ /.*\s+(.*)$/) {
      print "\nmatched ",$1,"\n";
    }
    

    这是为 i486-linux-gnu-thread-multi 构建的 perl v5.8.8

    【讨论】:

    • 字符串不匹配。我得到相同的输出。
    • 那一定是你传递字符串的方式。你能告诉我们你正在使用的确切命令吗?
    • 我正在从文件中读取字符串。它应该是自动转义的,对吧?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2011-12-05
    相关资源
    最近更新 更多