How to substitute arbitrary fixed strings in Perl
I want to replace a fixed string within another string using Perl. Both strings are contained in variables.
If it was impossible for the replaced string to contain any regex meta-characters, I could do something like this:
my $text = 'The quick brown fox jumps over the lazy dog!';
my $search = 'lazy';
my $replace = 'drowsy';
$text =~ s/$search/$replace/;
Alas, I want this to work for arbitrary fixed strings. E.g., this should leave $text
unchanged:
my $text = 'The quick brown fox jumps over the lazy dog!';
my $search = 'dog.';
my $replace = 'donkey.';
$text =~ s/$search/$replace/;
Instead, this replaces dog!
with donkey.
, since the dot matches the exclamation mark.
Assuming that the variable contents themselves are not hardcoded, e.g., they can come from a file or from the command line, is there a way to quote or otherwise markdown the contents of a variable so that they are no开发者_Go百科t interpreted as a regular expression in such substitution operations?
Or is there a better way to handle fixed strings? Preferably something that would still allow me to use regex-like features such as anchors or back-references.
Run your $search
through quotemeta
:
my $text = 'The quick brown fox jumps over the lazy dog!';
my $search = quotemeta('dog.');
my $replace = 'donkey.';
$text =~ s/$search/$replace/;
This will unfortunately not allow you to use other regex features. If you have a select set of features you want to escape out, perhaps you can just run your $search
through a first "cleaning" regex or function, something like:
my $search = 'dog.';
$search = clean($search);
sub clean {
my $str = shift;
$str =~ s/\./\\\./g;
return $str;
}
Wrap your search string with \Q...\E
, which quotes any meta characters within.
$text =~ s/\Q$search\E/$replace/;
#Replace a string without using RegExp.
sub str_replace {
my $replace_this = shift;
my $with_this = shift;
my $string = shift;
my $length = length($string);
my $target = length($replace_this);
for(my $i=0; $i<$length - $target + 1; $i++) {
if(substr($string,$i,$target) eq $replace_this) {
$string = substr($string,0,$i) . $with_this . substr($string,$i+$target);
return $string; #Comment this if you what a global replace
}
}
return $string;
}
精彩评论