Perl qr //および置換
-
11-07-2019 - |
質問
Getopsを使用してユーザー入力を取得する小さなプログラムを作成しています。それに基づいて、プログラムはパターンとテキストを一致させるか、一致したテキストをテキストに置き換えます。
私が抱えている問題は、置換部分を機能させることができないことです。 manページのqr //エントリを見ています: http ://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators ですが、運がありません。この場合のドキュメントとまったく同じようにコードをモデル化しようとしました。一致パターンをコンパイルし、置換に置き換えます。
どこが間違っているのか誰かが指摘できますか? (セキュリティについてはあまり気にしないでください。これは個人用のほんの小さなスクリプトです)
これは私が見ているものです:
if($options{r}){
my $pattern = $options{r};
print "\nEnter Replacement text: ";
my $rep_text = <STDIN>;
#variable grab, add flags to pattern if they exist.
$pattern .= 'g' if $options{g};
$pattern .= 'i' if $options{i};
$pattern .= 's' if $options{s};
#compile that stuff
my $compd_pattern = qr"$pattern" or die $@;
print $compd_pattern; #debugging
print "Please enter the text you wish to run the pattern on: ";
my $text = <STDIN>;
chomp $text;
#do work and display
if($text =~ s/$compd_pattern/$rep_text/){ #if the text matched or whatever
print $text;
}
else{
print "$compd_pattern on \n\t{$text} Failed. ";
}
} #end R FLAG
-r&quot; / matt /&quot;で実行すると-i、置換テキスト「matthew」をテキスト「matt」に入力すると、失敗します。これはなぜですか?
編集:
ご回答ありがとうございます!それは本当に助かりました。私はあなたの両方の提案を問題の実用的な解決策にまとめました。 / gフラグを少し異なる方法で処理する必要があります。作業サンプルは次のとおりです。
if($options{r}){
my $pattern = $options{r};
print "\nEnter Replacement text: ";
my $rep_text = <STDIN>;
chomp $rep_text;
#variable grab, add flags to pattern if they exist.
my $pattern_flags .= 'i' if $options{i};
$pattern_flags .= 's' if $options{s};
print "Please enter the text you wish to run the pattern on: ";
my $text = <STDIN>;
chomp $text;
#do work and display
if($options{g}){
if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/g){ #if the text matched or whatever (with the g flag)
print $text;
}
else{
print "$pattern on \n\t{$text} Failed. ";
}
}
else{
if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/){ #if the text matched or whatever
print $text;
}
else{
print "$pattern on \n\t{$text} Failed. ";
}
}
} #end R FLAG
解決
カオスが指摘するように、 qr //
を使用するといくつかの問題が発生します。あなたは本当にパターンをプリコンパイルする必要がありますか?そうでない場合、次のような戦略が機能する可能性があります。
my $pattern = 'matt';
my $text = 'Matt';
my $rep_text = 'Matthew';
my $pattern_opts = 'i';
print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/;
新しいコードに応じて更新する:次のようなアプローチの使用を検討できます。
my ($orig, $patt, $rep, $flags) = qw(FooFooFoo foo bar ig);
my $make_replacement = $flags =~ s/g// ?
sub { カオスが指摘するように、 qr //
を使用するといくつかの問題が発生します。あなたは本当にパターンをプリコンパイルする必要がありますか?そうでない場合、次のような戦略が機能する可能性があります。
my $pattern = 'matt';
my $text = 'Matt';
my $rep_text = 'Matthew';
my $pattern_opts = 'i';
print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/;
新しいコードに応じて更新する:次のようなアプローチの使用を検討できます。
<*>[0] =~ s/(?$flags:$patt)/$rep/g } :
sub { カオスが指摘するように、 qr //
を使用するといくつかの問題が発生します。あなたは本当にパターンをプリコンパイルする必要がありますか?そうでない場合、次のような戦略が機能する可能性があります。
my $pattern = 'matt';
my $text = 'Matt';
my $rep_text = 'Matthew';
my $pattern_opts = 'i';
print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/;
新しいコードに応じて更新する:次のようなアプローチの使用を検討できます。
<*>[0] =~ s/(?$flags:$patt)/$rep/ }
;
if ( $make_replacement->($orig) ){
print $orig;
}
else {
print "Failed...";
}
他のヒント
-r&quot; / matt /&quot;
ではなく、 -r&quot; matt&quot;
で実行します。オプション文字列にパターン区切り文字を指定する必要はありませんし、実際には指定できません。引用符は、 qr
の区切り文字です。そのため、実際には、スラッシュで囲まれた matt
を探しています。これは、実行方法です。パターン文字列をソースコードのように扱うようPerlに指示するために引用符を使用しようとしていますが、残念ながらそれはできません。
他のオプションに対して行っているこれらのパターン付加もすべて機能しません。すべてを行うには、正規表現のコンパイル方法を変更する必要があります。このような何かが / i
と / s
に対してそれを行うかもしれません:
my $compd_pattern = qr/$pattern/ or die $@;
$compd_pattern = qr/$compd_pattern/i if $options{i};
$compd_pattern = qr/$compd_pattern/s if $options{s};
/ g
の場合、検索/置換の代替バージョンをサポートする必要があります。 / g
は、 qr //
の有効な修飾子ではありません。