2016-09-02 22 views
2

文字列の検索/置換

私は、ユーザーがテキスト、検索パターン、および置換文字列を入力するPerlプログラムを持っています。

、ユーザが置換文字列に変数($1など)またはバックスラッシュエスケープ(のような\uまたは\L)を取り込む入力した場合、私は、置換文字列による検索パターンを交換するs///演算子を使用しますが、このシナリオでいます置換パターンはこれらのメタキャラクタを処理する必要がありますが、文字列として扱います。

#!/usr/bin/perl -w 

use strict; 

chomp(my $text = <STDIN>); #read the text 
chomp(my $regex = <STDIN>); #read the search pattern 
chomp(my $replace = <STDIN>); #read the replacement pattern 

$text=~s/$regex/$replace/g; # do replacement 

print $text,"\n"; 

このコードのためのサンプル入力が

fred flintstone and wilma flintstone are good couples 
(fred|wilma) flintstone 
\u\L$1\E Flintstone 

出力されるIは、方法を発見した

\u\L$1\E Flintstone and \u\L$1\E Flintstone are good couples 

される上記のコードのためのものである:

Iは、次のコードを持っています次のコードでこれを修正してください:

このコードは

Fred Flintstone and Wilma Flintstone are good couples 

として正しい出力を与える

#!/usr/bin/perl -w 

use strict; 

chomp(my $text = <STDIN>); 
chomp(my $regex = <STDIN>); 
chomp(my $replace = <STDIN>); 

$replace = '"' . $replace . '"'; # creating the string as '"\u\L$1\E Flintstone"' 

$text = ~s/$regex/$replace/gee; # applying double evaluation 

print $text,"\n"; 

は、今私は、この問題のためのよりよい方法があるかどうかを知りたいですか?ユーザが入力した任意の並べ替えのコードを実行することは常に危険であり、さらには単純な文字列は、可能性があります

+2

いいえ、いい方法はないと思います。 's ///'で評価オプションを使わなければなりません。ただし、ユーザーを信頼しないと危険です。 – redneb

+1

参照[ユーザーから右側が入力されているときにs ///演算子でee修飾子を安全に使用する](http://stackoverflow.com/questions/29107353/using-the-ee-modifier-safely-with-右手側入力時) –

+1

..そして[String :: Substitution](https://metacpan.org/pod/String::Substitution) –

答えて

4

二重引用符で囲まれた文字列は、それが

/ee修飾子はevalと同じ警告を運ぶコンパイルせずに補間することができませんユーザが入力するのが好き任意のPerlコードからなるブロックが含まれている、"my dangerous string @{ unlink glob '*.*'}"

のように私はあなたが "で補間を実行するためにSafeモジュールを使用しますsafe_interpolate関数をエクスポートし、優れString::Interpolateモジュールの使用を作ることを示唆しています安全な区画

#!/usr/bin/perl 

use strict; 
use warnings 'all'; 

use String::Interpolate 'safe_interpolate'; 

my $text = 'fred flintstone and wilma flintstone are good couples'; 
my $regex = '(fred|wilma) flintstone'; 
my $replace = '\u\L$1\E Flintstone'; 

$text =~ s/$regex/ safe_interpolate($replace) /eg; # do replacement 

print $text,"\n"; 
4

(まず、-wを使用しないでください。それはあなたの問題のために2000年(レキシカルスコープ、より予測)use warningsプラグマ)

に取って代わられています、あなたは「JavaScriptののString.prototype.replaceのクローン」であるData::Mungeモジュールからreplaceを使用することができます。

use Data::Munge qw(replace); 

$text = replace($text, $regex, $replace, 'g'); 

これは$&または$1ではなく、そのような\uとしてバックスラッシュシーケンスのようなものを拡大していきます。そのためには、独自の拡張関数を指定することもできますが、置換文字列内の特殊シーケンスを手動で解析して置き換える必要があります。 $1と友人の場合は、これは簡単ですが、\Ufoo\Q$1\Ebar\Ebazのようなものは、特に$1'\E'(歴史的にはこの領域にはPerl自体にも問題があります)が含まれていると、正しく処理するのが難しいです。しかし、あなたがその部分を働かせたら、replaceに接続するのは簡単です。

関連する問題