Perl正则表达式替换字边界。将“/”检测为单词边界

时间:2010-08-12 02:41:17

标签: regex perl word-boundary

我遇到了一个奇怪的正则表达式问题.... 我有一个文件,我正在做一个替换...作为一个例子我想要替换 带有“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”替换为“DEXX / AREX / CUBE”当它发现它是一个独立的单词而不是像“DEXX / AREX”这样的另一个组合的一部分时,要替换“AREX”

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

5 个答案:

答案 0 :(得分: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/CUBE

当然,如果您只有两个键,则不必使用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

答案 1 :(得分:2)

单词边界是\w\W之间的任何时间的转换,如果您正在处理ASCII,则可以说是[a-zA-Z0-9_][^a-zA-Z0-9_]

你应该能够通过使用负面的lookbehind来解决这个问题:

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

答案 2 :(得分:2)

\ b相当于(虽然比(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))效率更高)。如果你想要一组不同于默认字符的单词字符,只需使用它,但用适当的字符类替换\ w。

答案 3 :(得分:1)

首先,我感谢思南(他不是关于Perl的问题吗?我知道我已经潜伏了很长时间......)和ysth。多亏了这两个,我对正则表达式有了更好的把握。我的解决方案是以下......

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

我遇到的问题是我更换了替换件!通常情况下,我真的试着把这些事情搞清楚,但这是一个如此紧迫的截止日期和思南和你们,你们两个都严厉摇滚! 艾米

答案 4 :(得分:0)

\b的角度来看,界限往往不是你想要的,特别是考虑到英语单词可以包含撇号和破折号,并且当你放置\b时这些行为与字母的行为非常不同在他们旁边。有关此问题的更多说明,请参阅this answer如何应对此问题。