为什么替换时1美元是空的?

时间:2008-12-05 16:46:33

标签: regex perl substitution

我正在尝试将括号中的内容放入img标记中src属性的值中:

while(<TOCFILE>)
{
    $toc_line = $_;
    $toc_line =~ s/<inlineFig.*?(\.\.\/pics\/ch09_inline99_*?\.jpg)*?<\/inlineFig>/<img src="${1}" alt="" \/\>/g;
    $new_toc_file .= $toc_line;
}

所以我希望在输出中看到这样的标签:

<img src="../pics/ch09_inline99_00" alt="" />

但相反,我得到了:

<img src="" alt="" />

3 个答案:

答案 0 :(得分:12)

正则表达式中存在错误,因此该词组永远不会匹配任何内容:

inline99_*?\.jpg
        ^^^ 

我认为你在明星面前忘了\d,从你想要匹配的示例数据来判断。

你甚至没有要求它匹配,因为你在被捕获的组之后加了*?。所以,它只是不匹配任何东西。这就是你得到的:没有。

此外:

($PATTERN)*?

只会抓取它匹配的最后一件事。那也许不是你想要的。 例如:

$_ = 'one two three';
s/(\w+\s*)*/$1/;
print;

打印“三”。

答案 1 :(得分:3)

1)可以使用你正在解析的一些例子。

2)如果在表达式的末尾使用“x”,则可以在正则表达式中放置空格和注释以使其更容易理解

3)另外,通过分解它,你会注意到()里面的东西的第二部分缺少数字匹配...而是寻找0或更多'_',然后打破它看到数字,因此不匹配。

while(<TOCFILE>)
{
    $toc_line = $_;
    $toc_line =~ 
      s/                  # replace the follwoing     

         <inlineFig                     # match this text             
         .*?                            # then any characters until the next sequence matches
         (                              # throw the match into $1
            \.\.\/pics\/ch09_inline99_  # ..\pics\cho9_inline99_
            \d*?\.jpg                   # folowed by 0 or more numbers
         )*?                            # keeping doing that until the next sequence matches
         <\/inlineFig>                  # match this text

       /                  # with the follwoing


         <img src="${1}" alt="" \/\>    # some text and the result of $1 above.

       /xg;  # <- the x makes it ignore whitespace and #comments
    $new_toc_file .= $toc_line;
}

4)如上所述,()*?只返回最后一个匹配到1美元,但如果您的输入只是某种格式,这不应该是一个问题。

答案 2 :(得分:1)

修改你的模式,如bart建议的那样,并考虑使用“topic”变量$ _而不是显式地将从文件句柄读取的数据分配给另一个变量。

#!/usr/bin/perl

use warnings;
use strict;

my $new_toc_file;

{
    # localizing $_ protects any existing value in the global $_
    # you should localize $_ even if you choose to assign it to a variable

    local $_;

    while(<DATA>) { 
        # in the absence of the bind operator =~, s/// operates against $_
        s!<inlineFig.*?(\.\./pics/ch09_inline99_.*?\.jpg)</inlineFig>!<img src="$1" alt="" />!g;
        $new_toc_file .= $_;
    }
}

print $new_toc_file, "\n";

__END__
<inlineFig>../pics/ch09_inline99_00.jpg</inlineFig>