2012-03-15 2 views
13

perl 정규식을 사용하여 주어진 문자열에서 여러 특수 문자를 이스케이프 처리하려고합니다. 그것은 달러 기호를 제외한 모든 문자에 대해 잘 작동합니다. 나는 시도 다음

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; 

답변

17

이 시도 :

my %special_characters; 
$special_characters{"_"} = "\\_"; 
$special_characters{"\\\$"} = "\\\$"; 
$special_characters{"{"} = "\\{"; 
$special_characters{"}"} = "\\}"; 
$special_characters{"#"} = "\\#"; 
$special_characters{"%"} = "\\%"; 
$special_characters{"&"} = "\\&"; 

오른쪽 이상한 같은데? 귀하의 정규식은 다음과 같이 볼 필요가있다 :

s/\$/\$/g 

을 정규 표현식의 첫 부분에서 "$"는 문자열의 끝을 나타내는 특수 정규식 문자이기 때문에, 이스케이프 할 필요가있다.

정규 표현식의 두 번째 부분은 "일반"문자열로 간주되며 "$"는 특별한 의미가 없습니다. 따라서 백 슬래시는 실제 백 슬래시이고 첫 번째 부분에서는 달러 기호를 벗어나기 위해 사용됩니다.

변수 정의에서 백 슬래시와 달러 기호를 모두 이스케이프해야합니다. 둘 다 큰 따옴표로 묶인 문자열에 특별한 의미가 있기 때문입니다.

+2

더 나은 접근법 :'quotemeta()'또는's/\ Q $ char \ E/...'를 사용하십시오. 모든 $ 변수에 대해 regexps가이를 보간하기 때문에 이것을 기억해야합니다. – hhaamu

0

$은 regexp에서 특별한 의미를 갖습니다. 즉 "end of string"입니다. 이 같은 더 나을 것 :

# escape special characters, join them into a single line 
my $chars = join '', map { "\\$_" } keys %special_characters; 
$string =~ s/([$chars])/$special_characters{$1}/g; 

또한, 펄이 더 많은 "$"을 좋아 '$' (작은 따옴표 => 없음 보간)를 사용하지 않습니다.

UPDATE : 미안 해요, 난 서둘러이 작성되었다 => 너무 많은 편집 :(자체가 앞에 백 슬래시와 각 문자를 교체하는 경우

+0

귀하의 의견에 감사드립니다. 귀하의 솔루션은 정말 멋져 보입니다! 그러나 나는 더 쉬운 코드 (팀웍)를 사용할 의무가있다 ... 작은 따옴표에 감사드립니다. –

1

당신은 해시를 그냥 필요가 없습니다. 당신이 필요로하는 것과 일치하고 그것의 앞에 백 슬래시를 넣어 :. 모든 문자에 대해 정규 표현식을 구축하기

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에 문자를 넣어. 다른 모든 일이 일어납니다.

관련 문제