Çift ters eğik çizgi ile tüm tek ters eğik çizgiler


122

Ben dönüştürmek çalışıyorum String \something\içine String \\something\\kullanarak replaceAll, ama ben her türden hatayı almaya devam. Bunun çözüm olduğunu düşündüm:

theString.replaceAll("\\", "\\\\");

Ancak bu, aşağıdaki istisnayı verir:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1

Yanıtlar:


204

String#replaceAll()Bir şekilde argüman yorumlamaktadır düzenli ifade . \Bir kaçış karakteridir hem String ve regex. Normal ifade için çift çıkış yapmanız gerekir:

string.replaceAll("\\\\", "\\\\\\\\");

Ancak bunun için mutlaka bir düzenli ifadeye ihtiyacınız yoktur, çünkü karakter karakter tam bir değişim istiyorsanız ve burada kalıplara ihtiyacınız yoktur. Bu yüzden String#replace()yeterli olmalı:

string.replace("\\", "\\\\");

Güncelleme : yorumlara göre, dizeyi JavaScript bağlamında kullanmak istiyorsunuz. Bunun StringEscapeUtils#escapeEcmaScript()yerine daha fazla karakteri kaplamak için kullansan daha iyi olur .


Aslında, kaynağa geri dönüştürülmesi gereken bir JavaScript AST'de kullanılır. Çözümünüz işe yarıyor. Teşekkürler!
Frank Groeneveld

2
String#replaceAll()Yine de kullanmak istiyorsanız, değiştirilen dizeyi Matcher # quoteReplacement () ile alıntılayabilirsiniz :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
phse

Matcher.quoteReplacement (...) iyi bir yoldur! Lütfen Pshemo'nun cevabına bakın!
Hartmut P.

14

Bu tür sorunlardan kaçınmak için replace, replaceAll(normal bir ifade alan ) yerine (düz bir dize alır) kullanabilirsiniz. Yine de ters eğik çizgilerden kaçmanız gerekecek, ancak normal ifadelerde gerekli olan vahşi yollardan değil.


10

TLDR: theString = theString.replace("\\", "\\\\");bunun yerine kullanın.


Sorun

replaceAll(target, replacement)için targetve kısmen için normal ifade (regex) sözdizimini kullanır replacement.

Sorun şu ki \, normal ifadede ( \dbasamağı temsil ediyor gibi kullanılabilir ) ve Dize hazır "\n"bilgisinde (satır ayırıcıyı temsil \"etmek veya normalde dize değişmezinin sonunu temsil eden çift tırnak sembolünden kaçmak için kullanılabilir ).

Her iki durumda da \sembol yaratmak için, önüne ilave koyarak ondan kaçabiliriz (onu özel karakter yerine değişmez hale getirebiliriz) \(örneğin "aracılığıyla dize değişmezlerinde kaçtığımız gibi \").

Dolayısıyla, sembolü targettemsil eden regex \için tutulması gerekecek \\ve böyle bir metni temsil eden dize değişmezinin benzemesi gerekecektir "\\\\".

Bu yüzden \iki kez kaçtık :

  • normal ifadede bir kez \\
  • String değişmezinde bir kez "\\\\"(her biri \olarak temsil edilir "\\").

Olması durumunda replacement \da özeldir. Gösterim $yoluyla diğer özel karakterlerden kaçmamızı $xsağlar, normal ifade ile eşleşen ve indekslenmiş grup tarafından tutulan verilerin bir kısmını kullanmamıza izin verir x, tıpkı "012".replaceAll("(\\d)", "$1$1")her bir rakamla eşleşecek, onu yakalama grubu 1'e yerleştirecek ve $1$1iki kopyasıyla değiştirecektir. (onu çoğaltacaktır) sonuçlanır "001122".

Öyleyse yine, kelimenin tam anlamıyla replacementtemsil edilmesine izin vermek \için, ondan ek olarak kaçmamız gerekir, \bu da şu anlama gelir:

  • değiştirme iki ters eğik çizgi karakteri içermelidir \\
  • ve \\gibi görünen String değişmez değeri"\\\\"

AMA iki ters eğik çizgiyi replacementtutmak istediğimiz için ihtiyacımız olacak (her biri bir ile temsil edilir )."\\\\\\\\"\"\\\\"

Böylece sürüm replaceAllşuna benzeyebilir:

replaceAll("\\\\", "\\\\\\\\");

Daha kolay yol

Hayatı kolaylaştırmak için Java, metnin targetve replacementbölümlerin içine otomatik olarak kaçmak için araçlar sağlar . Artık yalnızca dizelere odaklanıp normal ifade sözdizimini unutabiliriz:

replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))

bizim durumumuzda böyle görünebilir

replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))

Daha iyi

Regex sözdizimi desteğine gerçekten ihtiyacımız yoksa, hiç dahil etmemeye izin verelim replaceAll. Bunun yerine kullanalım replace. Her iki yöntem de tüm target URL'lerin yerini alır , ancak replacenormal ifade sözdizimini içermez. Böylece yazabilirsin

theString = theString.replace("\\", "\\\\");

7

Normal bir ifade olduğundan ilk bağımsız değişkendeki (çıkış karakterli) ters eğik çizgiden kaçmanız gerekir. Değiştirme (2. bağımsız değişken - bkz. Eşleştirici # replaceAll (Dize) ) ayrıca ters eğik çizgilerin özel bir anlamını da içerir, bu nedenle bunları şu şekilde değiştirmeniz gerekir:

theString.replaceAll("\\\\", "\\\\\\\\");

3

Evet ... Düzenli ifade derleyicisi verdiğiniz deseni gördüğünde, yalnızca tek bir ters eğik çizgi görür (Java'nın sözlüğü çift ters vuruşu tek bir ters eğik çizgi haline getirdiğinden). İster inanın ister inanmayın "\\\\"ile değiştirmeniz gerekiyor "\\\\"! Java gerçekten iyi bir ham dizge sözdizimine ihtiyaç duyar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.