0

我遇到了一个奇怪的正则表达式问题......我有一个文件,我正在做一个替换......作为一个例子,我想用“DEXX / AREX”替换“DEXX”,然后用下一个替换替换...... . "AREX" 与 "AREX/CUBE"

DEXX 和 AREX 像这样存储在哈希中.... "DEXX" => "AREX", "AREX" => "CUBE"

我的正则表达式是这个......

foreach (keys %hashstore){
    $doc=~s!\b($_)\b!$1/$hashstore{$_}!ig;
}

发生的事情是“DEXX”正在被“DEXX/AREX”替换,但是当遇到“DEXX/AREX”时,正则表达式正在用“DEXX/AREX/CUBE”替换“DEXX/AREX”,而它应该只替换“ AREX”,当它发现它是一个独立的词而不是另一个组合的一部分,如“DEXX/AREX”

它似乎将“/”检测为单词边界。有没有人遇到过这个或知道解决它的方法?非常感谢!艾米

4

5 回答 5

5

但是/是一个词的边界。从perldoc perlreref

\b匹配单词边界(在\w和之间\W)。

根据您在下面的评论,您应该避免循环:

#!/usr/bin/perl

use strict; use warnings;
use Regex::PreSuf;

my %lookup = (
    "DEXX" => "AREX",
    "AREX" => "CUBE",
);

my $doc = 'DEXX AREX AREX DEXX AREX DEXX DEXX DEXX AREX';
my $re = presuf keys %lookup;

$doc =~ s{($re)}{$1/$lookup{$1}}g;

print $doc, "\n";

输出:

DEXX/AREX AREX/CUBE AREX/CUBE DEXX/AREX AREX/CUBE DEXX/AREX DEXX/AREX DEXX/AREX
AREX/立方体

当然,如果您只有两个键,则不必使用Regex::PreSuf :

s{(AREX|DEXX)}{$1/$lookup{$1}}g;

也会做。但是,对于更长的键列表,我发现Regex::PreSuf非常方便。

更新:当然,如果键可以在任何情况下出现在文本中,您可以uc在查找替换时使用转换:

所以,要么

$doc =~ s{($re)}{join '/', uc($1), $lookup{uc $1}}eig;

或者

$doc =~ s{($re)}{join '/', $1, $lookup{uc $1}}eig;

取决于你需要什么。

此外,ysth在评论中指出“在 5.10 及更高版本中,Regex::PreSuf 在大多数情况下生成的正则表达式比天真的替换更差。” 所以,

my $re = join '|', map quotemeta, sort { length($b) <=> length($a) } keys %lookup; 

可能会更好。sort如果某些键可能是其他键的初始子字符串,则需要。

于 2010-08-12T02:49:54.983 回答
2

边界一词是指在\w和之间有过渡的任何时候\W,也就是说[a-zA-Z0-9_][^a-zA-Z0-9_]如果您正在处理 ASCII。

您应该能够通过使用否定的lookbehind来解决这个问题:

foreach (keys %hashstore){
    $doc=~s!(?<!/)\b($_)\b!$1/$hashstore{$_}!ig;
}
于 2010-08-12T02:50:58.023 回答
2

\b is equivalent to (though more efficient than) (?:(?<!\w)(?=\w)|(?<=\w)(?!\w)). If you want a different set of word characters than the default, just use that but with \w replaced by an appropriate character class.

于 2010-08-12T05:22:52.670 回答
1

首先,我要感谢 Sinan(谁不关心 Perl on SO?我知道我已经潜伏了很长时间......)和 ysth。多亏了这两个,我对正则表达式有了更好的掌握。然而,我的解决方案如下......

my $pat = join '|', keys(%hashstore);
$doc =~ s!\b($pat)\b!$1/$hashstore{uc($1)}!ig;

我遇到的问题是我更换了替代品!通常情况下,我真的会尝试解决这些问题,但这是一个如此紧迫的截止日期,而思南和 ysth,你们俩都摇滚得很厉害!艾米

于 2010-08-12T12:58:59.757 回答
0

从 of 的角度来看的边界\b通常不是您想要的,特别是考虑到英语单词可以包含撇号和破折号,并且当您将 a 放在\b它们旁边时,它们的行为与字母非常不同。有关此问题的更多解释以及如何处理,请参阅此答案。

于 2010-11-18T13:42:00.583 回答