2017-01-29 19 views
-1

私は、パラメータを取り込むfind_replaceサブルーチンを持っています(コンテンツ、正規表現の検索、正規表現の置き換え、結果変数の結果格納)。私はqr//を使用して、検索正規表現と置き換え正規表現の両方を渡します。 regexがうまく動作するが、regexを置き換えることはできません。qr //を使用してサブルーチンにRegExを置き換えます

$text = "11 22 33 44 55"; 
find_replace($text,qr/(33)(.*?)(55)/,qr/$1<BOLD>$2<\/BOLD>$3/,my $newText); 
print $newText; 
    #Should print: 11 22 <I>33 <B>44</B> 55</I> 
    #But it prints: 11 22 <I>(?^:<B></B>)</I> 

sub find_replace { 
    my $content = shift; 
    my $findRegEx = shift; 
    my $replaceRegEx = shift; 
    my $newVariable = \shift; 

    ${$newVariable} = $content; 
    ${$newVariable} =~ s/$findRegEx/<I>$replaceRegEx<\/I>/g; 
} 

私はこのための修正プログラムが動作するように見つけた:

$text = "11 22 33 44 55"; 
find_replace($text,qr/(33)(.*?)(55)/,sub{"$1<B>$2<\/B>$3"},my $newText); 
print $newText; 
    #Prints: 11 22 <I>33 <B>44</B> 55</I> 

sub find_replace { 
    my $content = shift; 
    my $findRegEx = shift; 
    my $replaceRegEx = shift; 
    my $newVariable = \shift; 

    ${$newVariable} = $content; 
    ${$newVariable} =~ s($findRegEx){ "<I>".$replaceRegEx->()."<\/I>" }ge; 
} 

しかし、この修正プログラムはsub{"…"}の代わりqr/…/使用しています。私が探しているのは、置換正規表現を渡して同じ結果を得るためにqr//を使い続けることです。

+4

交換部品*は正規表現*ではありません。それを一つにしようとしないでください。サブ{}方法はこれを行う正しい方法です。 – ysth

+0

あなたは何をする必要があるのか​​(たとえば)を参照してください[この投稿](http://stackoverflow.com/a/41280344/4653379) – zdim

+0

@zdimこのコードは、['Data :: Munge :: replace'](https://metacpan.org)を使用することで大幅に簡略化することができます。/pod/Data :: Munge#replace-STRING、-REGEX、-REPLACEMENT、-FLAG)。 – melpomene

答えて

1

replaceのテキストは正規表現ではなく、補間の準備ができている文字列であることを理解しておく必要があります。正規表現が必要な文字列に対して実行されるまで補間を遅らせるために回避策のようなことをする必要があります。

あなたのサブがこれほどシンプルであれば、私はあなたが実際にそれをサブに入れるべきかどうかは確信していません - sオペレータは既にサブコールであり、あなたはただ複雑です。もちろん、正規表現を渡す必要がある状況や、より複雑なサブにする必要がある状況がありますが、これは良いことですが、このタイプの遅延補間が必要です。

3

まず、置き換え式が正規表現パターンではないため、置換式にqr//を使用することは意味がありません。 qq//(二重引用符の付いた文字列)とq//(一重引用符の付いた文字列)を使用して文字列を構成します。

主な問題は

s/$findRegEx/<I>$replaceRegEx<\/I>/g 

my $repl_expr = sub { qq/<I>$replaceRegEx<\/I>/ }; # Interpolates $replaceRegEx 
s/$findRegEx/ $repl_expr->() /eg 

意味していますが、文字列から開始する必要がある場合は、あなたが本当に

my $repl_expr = sub { qq/$1<B>$2<\/B>$3/ };   # Interpolates $1, $2 and $3 
s/$findRegEx/ $repl_expr->() /eg 

をしたいということである(例えば置換式がから来ています設定ファイル)を使用すると、次のようなものを実現することができます:

use String::Substitution qw(gsub_copy); 

my $newText = gsub_copy($text, qr/(33)(.*?)(55)/, '$1<BOLD>$2</BOLD>$3'); 
関連する問題