0

奇妙な正規表現の問題が発生しています....置換を行っているドキュメントがあります...例として、「DEXX」を「DEXX/AREX」に置き換えてから、次の置換で置き換えたい.. . 「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」

「/」を単語境界として検出するようです。誰かがこれに遭遇したか、それに関する修正を知っていますか? どうもありがとう!エイミー

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 / アレックス アレックス / キューブ アレックス / キューブ デックス / アレックス アレックス / キューブ デックス / アレックス デックス / アレックス デックス / アレックス
アレックス/キューブ

もちろん、キーが 2 つしかない場合は、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はコメントで次のように指摘しています。そう、

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

良いかもしれません。一部のsortキーが他のキーの最初の部分文字列である可能性がある場合に必要です。

于 2010-08-12T02:49:54.983 に答える
2

\b は (より効率的ですが) と同等(?:(?<!\w)(?=\w)|(?<=\w)(?!\w))です。デフォルトとは異なる単語文字セットが必要な場合は、それを使用してください。ただし、\w は適切な文字クラスに置き換えてください。

于 2010-08-12T05:22:52.670 に答える
2

\wワード境界は、との間の遷移があるときです。\Wつまり[a-zA-Z0-9_][^a-zA-Z0-9_]と ASCII を扱っている場合です。

否定後読みを使用することで、この問題を回避できるはずです。

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

まず最初に、Sinan (SO の Perl に関係のない人は誰ですか? 私は長い間潜んでいたことを知っています....) と ysth にお世話になっています。この 2 つのおかげで、正規表現をよりよく理解できました。しかし、私の解決策は次のとおりでした...

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

私が抱えていた問題は、交換品を交換することでした!通常、私は本当にこれらのことをハッシュ化しようとしますが、これは非常にタイトな締め切りであり、Sinan と ysth、あなたは両方とも激しく揺れ動きます! エイミー

于 2010-08-12T12:58:59.757 に答える
0

の観点からの境界は\b、特に英単語にアポストロフィやダッシュが含まれる可能性があり、\bそれらの隣に a を配置した場合の文字とはまったく異なる動作をすることを考えると、多くの場合、あなたが望むものとはまったく異なります。この問題の詳細と対処方法については、この回答を参照してください。

于 2010-11-18T13:42:00.583 に答える