Подтвердить что ты не робот

Как избежать знака доллара ($) в строке с использованием регулярного выражения 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;
4b9b3361

Ответ 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 не нравится "$" много, лучше использовать '$' (одиночные кавычки = > нет интерполяции).

ОБНОВЛЕНИЕ: Извините, я написал это в спешке = > слишком много исправлений: (