2012-03-15 16 views
13

का उपयोग कर स्ट्रिंग में डॉलर चिह्न ($) से बचने के लिए कैसे मैं perl regex का उपयोग करके दिए गए स्ट्रिंग में कई विशेष वर्णों से बचने की कोशिश कर रहा हूं। यह डॉलर के संकेत को छोड़कर सभी पात्रों के लिए ठीक काम करता है। मैंने कोशिश की है: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; 

उत्तर

17

इस प्रयास करें:

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

अजीब है, है ना लग रहा है? आपका रेगुलर एक्सप्रेशन से कुछ ऐसा नज़र करने की जरूरत है:

s/\$/\$/g 

regex के पहले भाग में, "$" भाग निकले जा करने के लिए है, क्योंकि यह एक विशेष regex चरित्र स्ट्रिंग के अंत को संकेतित करते है की जरूरत है।

रेगेक्स का दूसरा भाग "सामान्य" स्ट्रिंग के रूप में माना जाता है, जहां "$" का कोई विशेष अर्थ नहीं है। इसलिए बैकस्लैश एक वास्तविक बैकस्लैश है जबकि पहले भाग में इसका उपयोग डॉलर के संकेत से बचने के लिए किया जाता है।

इसके अलावा परिवर्तनीय परिभाषा में आपको बैकस्लैश के साथ-साथ डॉलर के चिह्न से बचने की आवश्यकता है, क्योंकि उनमें से दोनों का डबल-उद्धृत तारों में विशेष अर्थ है।

+2

बेहतर दृष्टिकोण: 'quotemeta()' या 's/\ Q $ char \ E/... का उपयोग करें, आपको याद रखना चाहिए कि प्रत्येक $ चर के लिए ऐसा करना चाहिए, क्योंकि regexps उन्हें अलग करता है। – hhaamu

0

$ रेगेक्स में विशेष अर्थ है, अर्थात् "स्ट्रिंग का अंत"। आप कुछ इस तरह के साथ बंद बेहतर होगा:

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

इसके अलावा, पर्ल "$" ज्यादा पसंद नहीं करता है, बेहतर '$' (एकल उद्धरण => कोई प्रक्षेप) का उपयोग करें।

अद्यतन: क्षमा करें, मैं जल्दी में यह लिख रहा था => बहुत अधिक संपादन :(

+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 में चरित्र डाल दिया। बाकी सब कुछ आपके लिए होता है।