2016-04-03 12 views
0

içerir. Ben 23.0.1 ile dize 23.0 değiştirmek istiyor, bu yüzden bu çalıştı:, dize Arama ve Perl kullanarak bir dize yerine bir değişken kullanıyorum nokta

my $old="23.0"; 
    my $new="23.0.1"; 
    $_ =~ s/$old/$new/g;   

sorun da dize 2310 yerini olmasıdır, bu yüzden denedim:

my $old="23\.0" 

ve ayrıca /ee. Ancak, çalışması için doğru sözdizimini bulamıyoruz. Birisi bana doğru sözdizimini gösterebilir mi? - meta karakterlerinden kaçınmak olacaktır

quotemeta fonksiyonu:

cevap

3

burada yardımcı olacak iki şey vardır. Ve ayrıca regex interpolasyon durdurmak \Q ve \E regex bayraklar.

print quotemeta "21.0"; 

Veya: Bir çift: Sobrique mükemmel cevabı tamamlamak için

my $old="23.0"; 
my $new="23.0.1"; 
my $str = "2310"; 
$str =~ s/\Q$old\E/$new/g; 
print $str; 
+0

\ Q ve \ E regex özellikleri değil, çift tırnaklı enterpolasyon yaptığınız her yerde çalışırlar – ysth

0

, bana "23\.0" ile girişimi işe yaramadı nedeni "23\.0" ve "23.0" aynı dize olarak değerlendirilebilir olduğunu olduğuna dikkat edelim -quoted string literal, \. tersbölü kaçış dizisi . için değerlendirir. yapabilirsiniz, gerçekten sabit bir dizeyle eşleşen istiyorsanız

  • ve ihtiyaç veya içinde herhangi bir özel regexp meta dahil etmek istemiyoruz:

    Orada Bunu önlemek için yapabileceği pek çok şey vardır Sobrique'in önerdiği gibi yapın ve bunlardan kurtulmak için quotemeta veya \Q kullanın. eşleştirilecek dize kullanıcı girişi geliyorsa Özellikle

    , bu hemen hemen her zaman doğru bir çözümdür. Yapmanız Eğer olmayan edebi metakarakterlerin bazı sınırlı seti, o quotemeta aracılığıyla desen çalışan sonra okunabilir hale edebilir izin vermek istiyorum.

    : Basit bir örnek için buraya eşdeğer regexp içine ("herhangi bir karakter" ve repectively "herhangi bir karakter dizesi" için meta ? ve * kullanarak) temel glob benzeri desen açmak için bir kirli hızlı ve yönlü çalışıyor hemen bir şeye karşı eşleşen olmadan kodunuzda bir değişmez regexp desen yapmak istiyorsanız
    my $regexp = "^\Q$glob\E\$"; # quote and anchor the pattern 
    $regexp =~ s/\\\?/./g;  # replace "?" (escaped to "\?" by \Q) with "." 
    $regexp =~ s/\\\*/.*/g;  # replace "*" (escaped to "\*" by \Q) with ".*" 
    
  • Tersine, böyle qr// regexp'in benzeri alıntı operatörünü kullanabilirsiniz:

    my $old = qr/\b23\.0(\.0)?\b/; # match 23.0 or 23.0.0 (but not 123.012!) 
    my $new = "23.0.1";    # just a literal string 
    
    s/$old/$new/g;   # replace any string matching $old in $_ with $new 
    

    Not o qr//'un başka bir etkisi var aslında özel Normal ifade nesnesine deseni ön derler, bunun sonradan kullanıldığı her zaman yeniden derlenmesi gerekmez böylece: Sadece değişmezi bir dizede regexp sözdizimi kullanmasına izin ötesinde cts. Bir regexp olarak eşdeğer olacak olsa Özellikle, bir yan etki olarak, edebi bir qr// regexp'nin dize gösterimi genellikle tam olarak orijinal içeriği uymaz. Örneğin, say qr/\b23\.0(\.0)?\b/, Perl versiyonumda (?^u:\b23\.0(\.0)?\b) çıkışını verecektir.

  • Ayrıca sadece edebi normal çift tırnaklı dize kullanmak ve içinde herhangi bir ters eğik çizgi çift, ama bu (genellikle) var olabilir qr// kullanmaktan daha az verimli ve aynı zamanda nedeniyle leaning toothpick syndrome daha az okunabilir.

    Tek tırnaklı bir dizgenin harfini kullanmak biraz daha iyi olur, çünkü tek tırnaklı bir dizgede ters eğik çizgi sadece başka bir ters eğik çizgi veya tek tırnak işareti ile takip edildiğinde özeldir. Yine de, regexp'inizdeki herhangi bir gerçek ters eğik çizgi ile eşleşmeniz gerekiyorsa okunabilirlik yine de acı çekebilir, yine de ihtiyaç duyulan nadir yerlerin ters eğik çizgisini ikiye katlamayı unutursanız, ince hatalar oluşturmanın kolay olduğunu belirtmeyin.