Как избежать знака доллара ($) в строке с использованием регулярного выражения perl
Я пытаюсь избежать нескольких специальных символов в заданной строке, используя perl regex. Он отлично работает для всех персонажей, за исключением знака доллара. Я попробовал следующее:
my %special_characters;
$special_characters{"_"} = "\\_";
$special_characters{"$"} = "\\$";
$special_characters{"{"} = "\\{";
$special_characters{"}"} = "\\}";
$special_characters{"#"} = "\\#";
$special_characters{"%"} = "\\%";
$special_characters{"&"} = "\\&";
my $string = '$foobar';
foreach my $char (keys %special_characters) {
$string =~ s/$char/$special_characters{$char}/g;
}
print $string;
Ответы
Ответ 1
Попробуйте следующее:
my %special_characters;
$special_characters{"_"} = "\\_";
$special_characters{"\\\$"} = "\\\$";
$special_characters{"{"} = "\\{";
$special_characters{"}"} = "\\}";
$special_characters{"#"} = "\\#";
$special_characters{"%"} = "\\%";
$special_characters{"&"} = "\\&";
Выглядит странно, правда? Ваше регулярное выражение должно выглядеть следующим образом:
s/\$/\$/g
В первой части регулярного выражения "$" нужно экранировать, потому что это специальный символ регулярного выражения, обозначающий конец строки.
Вторая часть регулярного выражения рассматривается как "нормальная" строка, где "$" не имеет особого значения. Поэтому обратная косая черта - это настоящая обратная косая черта, тогда как в первой части она использовалась для выхода из знака доллара.
Кроме того, в определении переменной вам нужно избежать обратного слеша, а также знака доллара, потому что оба они имеют особое значение в строках с двойными кавычками.
Ответ 2
Вам не нужен хеш, если вы заменяете каждого символа, которому предшествует обратная косая черта. Просто сопоставьте то, что вам нужно, и поставьте перед ним обратную косую черту:
s/($re)/"\\$1"/eg;
Чтобы создать регулярное выражение для всех символов, Regexp:: Assemble действительно приятно.
use v5.10.1;
use Regexp::Assemble;
my $ra = Regexp::Assemble->new;
my @specials = qw(_ $ { } # % & );
foreach my $char ( @specials ) {
$ra->add( "\\Q$char\\E" );
}
my $re = $ra->re;
say "Regex is $re";
while( <DATA> ) {
s/($re)/"\\$1"/eg;
print;
}
__DATA__
There are $100 dollars
Part #1234
Outside { inside } Outside
Обратите внимание, что в первой строке ввода Regexp:: Assemble переустановил мой шаблон. Это не просто склеенные части частей, которые я добавил:
Regex is (?^:(?:[#$%&_]|\{|\}))
There are \$100 dollars
Part \#1234
Outside \{ inside \} Outside
Если вы хотите добавить больше символов, вы просто поместите символ в @specials
. Все остальное происходит для вас.
Ответ 3
$
имеет особое значение в regexp, а именно "конец строки". Вам будет лучше с чем-то вроде этого:
# escape special characters, join them into a single line
my $chars = join '', map { "\\$_" } keys %special_characters;
$string =~ s/([$chars])/$special_characters{$1}/g;
Кроме того, perl не нравится "$"
много, лучше использовать '$'
(одиночные кавычки = > нет интерполяции).
ОБНОВЛЕНИЕ: Извините, я написал это в спешке = > слишком много исправлений: (