我试图理解Perl中的这个正则表达式如何创建它所做的事情

时间:2016-11-04 09:08:11

标签: regex perl

$ row contains

<img alt="1688.jpg" src="http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg" />

执行以下语句后

$row =~ s/("(.+?)")(.+?)("(.+?)")/""$3$1/;

$row包含<img alt="" src="1688.jpg" />

这正是我想要的,但我无法弄清楚正则表达式如何设法填充以下内容。

$1 -> "1688.jpg"<br>
$2 -> 1688.jpg<br>
$3 ->  src= (it has a leading space)<br>
$4 -> "http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg"<br>
$5 -> http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg<br>

我认为如果我能够理解它是如何填充变量的话,我就不会花费这么长时间才能使它工作。有人可以向我解释一下吗?

3 个答案:

答案 0 :(得分:4)

捕获组从最左边到最右边开始编号(忽略一些嵌套的事实)。根据您的输入,捕获组编号如下:

$row =~ s/("(.+?)")(.+?)("(.+?)")/""$3$1/; 1 2 3 4 5

此外,?之后的.+表示它将匹配满足模式的最小值,在这种情况下,它将匹配它找到的第一个双引号。所以我们可以看到它捕获了以下内容(忽略单引号):

  1. &#39;&#34; 1688.jpg&#34;&#39;
  2. &#39; 1688.jpg&#39;
  3. &#39; SRC =&#39;
  4. &#39;&#34; http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg&#34;&#39;
  5. &#39; http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg&#39;
  6. 因为这是一个字符串替换,所以匹配的输入的整个部分将被正则表达式模式的第二部分(即""$3$1)替换。所以我们将替换(从第一个双引号到最后一个双引号):

    "1688.jpg" src="http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg"

    使用: "" src="1688.jpg"

    希望这有帮助。

答案 1 :(得分:1)

刚开始从左括号开始计算组,以查看捕获的内容。这是一个略带注释的版本:

#!/usr/bin/env perl

use strict;
use warnings;

my $row = '<img alt="1688.jpg" src="http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg" />';

#           1 2   2 13   34 5   5 4
my $re = qr/("(.+?)")(.+?)("(.+?)")/;

#          12      213   345                                                             54
# <img alt="1688.jpg" src="http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg" />';

$row =~ $re;
print "\n";
print "\$1 => '$1'\n";
print "\$2 => '$2'\n";
print "\$3 => '$3'\n";
print "\$4 => '$4'\n";
print "\$5 => '$5'\n";

$row =~ s/$re/""$3$1/;
print $row . "\n";

<强>输出

$1 => '"1688.jpg"'
$2 => '1688.jpg'
$3 => ' src='
$4 => '"http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg"'
$5 => 'http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg'
<img alt="" src="1688.jpg" />

答案 2 :(得分:0)

正如人们在我之前解释的那样,每次使用括号时都会创建一个捕获组。

我发现防止混淆或不得不计算括号的最佳方法是明确不要通过将?:放在开头括号之后来捕捉您不需要的内容。

use Data::Dumper;

my $s = '<img alt="1688.jpg" src="http://res.cloudinary.com/stw/image/upload/v1478118784/1688.jpg" />';

my @row = $s =~ /("(.+?)")(.+?)("(.+?)")/;

# only capture quoted things
my @row1 = $s =~ /(?:"(.+?)")(?:.+?)(?:"(.+?)")/;

print Dumper \@row;
print Dumper \@row1;