【问题标题】:a simple string substitution does not work简单的字符串替换不起作用
【发布时间】:2013-02-28 20:59:09
【问题描述】:

以下是我的代码:

my $string1 = '<td><a href="http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3">abcdefg</a><br />(123456)</td>';
my $string2 = 'http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3';


print "Before string substitution:\n$string1\n";
$string1 =~ s/$string2//;
print "After string substitution:\n$string1\n"; 

以及实际输出:

Before string substitution:
<td><a href="http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3">abcdefg</a><br />(123456)</td>
After string substitution:
<td><a href="http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3">abcdefg</a><br />(123456)</td> 

我的期望:

Before string substitution:
<td><a href="http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3">abcdefg</a><br />(123456)</td>
After string substitution:
<td><a href="">abcdefg</a><br />(123456)</td> 

有人可以告诉我我的代码有什么问题吗?

谢谢。

【问题讨论】:

  • HTML 和正则表达式,致命的吸引力。
  • @MkV 你的意思是上瘾

标签: string perl substitution


【解决方案1】:

可以通过在脚本中添加两个字符来解决该问题。您需要的是在$string2 中转义元字符:

$string1 =~ s/\Q$string2//;

导致匹配失败的字符是问号?,这里未转义的...aspx?...表示“匹配字符'x'的0或1”。字符. 是匹配除换行符之外的任何内容的通配符,这可能会导致误报匹配。斜线/ 虽然是元字符,因为它是替换运算符s/// 的分隔符,但不需要转义,因为它们嵌入在字符串中。

转义元字符最容易使用\Q ... \E 转义序列、在正则表达式中或quotemeta 完成。

尝试手动转义这些类型的字符串并不是一个好主意,尤其是在只需要文字匹配的情况下。

【讨论】:

  • ? 是唯一阻止它匹配的字符。这两个. 也可能成为麻烦
  • @BradGilbert 我不确定你的这条评论是什么意思。
  • 如果你只修复了?。它仍然可以匹配http://www_aaa.com/downloads/details.aspx?FamilyID=a1b2c3(将第一个. 替换为_)。这会使第一个. 成为问题。 (评论主要是为这个答案的未来观众)
  • @brad 我提出的解决方案不存在元字符问题。
  • 我知道不是。如果有类似问题的人只是反斜杠?,他们仍然可能有问题。一个更难找到。我想应该有一些东西指出,使用quotemeta\Q ... \E 可以解决其他尚不明显的问题。
【解决方案2】:

由于您输入的字符被 perl 正则表达式视为特殊字符,因此您必须像这样将它们转义:

my $string2 = 'http:\/\/www\.aaa\.com\/downloads\/details\.aspx\?FamilyID=a1b2c3';

然后当你运行你的程序时会出现预期的输出:

<td><a href="http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3">abcdefg</a><br />(123456)</td>
After string substitution:
<td><a href="">abcdefg</a><br />(123456)</td>

要从字符串中转义这些字符,最好只使用 perl 的 quotemeta 函数:

my $string2 = quotemeta('http://www.aaa.com/downloads/details.aspx?FamilyID=a1b2c3');

这将为您转义特殊字符,然后您的正则表达式替换将正常工作。

编辑

由于您遇到问题是因为非转义的正则表达式字符,因此此解决方案可能更简单,因为它不需要您转义任何字符:

substr($string1, index($string1,$string2), length($string2)) = '';

这是基于这个例子:

my $name = 'fred';
substr($name, 4) = 'dy'; # $name is now 'freddy'

substr 的 perldocs 中找到。

【讨论】:

  • 你绝对是在正确的轨道上;主要的麻烦制造者是?;在这种情况下,斜杠实际上不是问题(仅在 ? 前面放一个反斜杠,然后尝试一下)。 . 字符将匹配 . 非常高兴(以及其他任何东西)。事实上,字符串不太可能因为点而引起问题。
  • @JonathanLeffler,知道了。感谢您的澄清! :)
  • 您的substr 示例几乎应该是{my $index=index($string1,$string2);if($index &gt;= $[){substr($string1,$index,length($string2),'')}}。如果不匹配,您现在将空字符串附加到 $string1 的末尾。目前这不是什么大问题,但将来当COW 字符串成为默认值时,它可能会导致不必要的复制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 2015-06-24
  • 2019-01-08
  • 2016-02-15
  • 2016-10-05
  • 2012-07-08
相关资源
最近更新 更多