Bir normal ifadede öncelenmesi gereken tüm özel karakterlerin listesi


108

Bir mesaj şablonunu bir kullanıcının göndermeye çalıştığı bir mesajla eşleştiren bir uygulama oluşturmaya çalışıyorum. İletiyi eşleştirmek için Java regex kullanıyorum. Şablon / mesaj özel karakterler içerebilir.

Normal ifademin mümkün olan maksimum durumlarda çalışması ve eşleşmesi için kaçılması gereken özel karakterlerin tam listesini nasıl alabilirim?

Java regex'indeki tüm özel karakterlerden çıkış yapmak için evrensel bir çözüm var mı?

Yanıtlar:


94

Pattern sınıfının javadoc'una bakabilirsiniz: http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html

Özel anlam yerine normal karakteri istiyorsanız, orada listelenen tüm karakterlerden kaçmanız gerekir.

Belki daha basit bir çözüm olarak, şablonu \ Q ve \ E arasına koyabilirsiniz - aralarındaki her şey kaçmış olarak kabul edilir.


43
\ Q ve \ E'yi hatırlamakta zorlanıyorsanız, bunun yerine Pattern.quote ("...") kullanabilirsiniz
mkdev

19
Keşke bunları gerçekten belirtmiş olsaydın
Aleksandr Dubinsky

Neden @AleksandrDubinsky?
Sorin

55
@Sorin Sadece site dışı bir kaynağa bağlanmaktan ziyade cevabınızda cevabı belirtmek Stack Exchange'in ruhudur (hayır, politika?). Ayrıca o sayfanın da net bir listesi yok. : Bir liste burada bulunabilir docs.oracle.com/javase/tutorial/essential/regex/literals.html , henüz "Belli durumlarda yukarıda listelenen özel karakterler olacak devletler değil ne olacağını açıklayan olmadan meta karakterler olarak tedavi edilebilir" eğer biri onlardan kaçmaya çalışırsa. Kısacası, bu soru iyi bir cevabı hak ediyor.
Aleksandr Dubinsky

8
"Bunlar [ \Qve \E] arasındaki her şey kaçmış olarak kabul edilir" - diğer \Q'ler ve \E' ler (orijinal normal ifadede olabilir) hariç . Bu nedenle, buradaPattern.quote önerildiği gibi kullanmak ve tekerleği yeniden icat etmemek daha iyidir .
Sasha

92
  • Normal ifadelerde öncelenmesi gereken Java karakterleri şunlardır:
    \.[]{}()<>*+-=!?^$|
  • Kapatma parantezlerinden ikisinin ( ]ve }) yalnızca aynı tip braket açıldıktan sonra kaçılması gerekir.
  • Gelen []-brackets bazı karakterler (gibi +ve -) kaçış olmadan bazen işi yapmak.

Kaçmamanın ama bu karakterlere izin vermenin bir yolu var mı?
Dominika

1
Bir karakterden kaçmak, onu bir operatör olarak yorumlamak yerine karaktere izin vermek anlamına gelir.
Tobi G.

4
Aralığın tanımlanmasında kullanıldığından, -içinde çıkış karakteri []her zaman çalışmayabilir. Ondan kaçmak daha güvenli. Örneğin, desenler [-]ve [-)]dizeyle eşleşir -ancak ile eşleşmez [(-)].
Kenston Choi

1
Kabul edilen cevap soruyu cevaplasa da, sadece hızlı bir liste ararken bu cevap bana daha yardımcı oldu.
Old Nick

-=!mutlaka kaçılmasına gerek yoktur, bağlama bağlıdır. Örneğin, tek bir harf olarak sabit bir normal ifade olarak çalışırlar.
Hawk

29

Kaçmak için bunu Java 1.5'ten kullanabilirsiniz :

Pattern.quote("$test");

Kelimeyle tam olarak eşleşeceksin $test


Neden bu en yüksek puan alan cevap değil? Kaçılması gereken tüm karakterleri listelemenin karmaşık ayrıntılarına girmeden sorunu çözer ve JDK'nın bir parçasıdır - fazladan kod yazmaya gerek yoktur! Basit!
Volksman

17

Göre Dizi Hazır / Metakarakter dokümantasyon sayfasından, bunlar şunlardır:

<([{\^-=$!|]})?*+.>

Ayrıca bu listenin kodda bir yerde hakemlik edilmesi harika olurdu, ama bunun nerede olabileceğini bilmiyorum ...


11
String escaped = tnk.replaceAll("[\\<\\(\\[\\{\\\\\\^\\-\\=\\$\\!\\|\\]\\}\\)\\?\\*\\+\\.\\>]", "\\\\$0");
marbel82

1
Kalıp javadoc, kaçan bir yapıyı belirtmeyen herhangi bir alfabetik karakterden önce ters eğik çizgi kullanmanın bir hata olduğunu söyler, ancak bu karakterin çıkış karaktersiz bir yapının parçası olup olmadığına bakılmaksızın alfabetik olmayan bir karakterden önce bir ters eğik çizgi kullanılabilir. Bu nedenle, çok daha basit bir normal ifade yeterli olacaktır: kelime olmayan karakterleri belirleyen s.replaceAll("[\\W]", "\\\\$0")yerde \W.
Joe Bowbeer 01

6

Herkesin söylediklerini birleştirerek, RegExp'e özel karakterlerin listesini kendi String'lerinde açıkça listelenmiş halde tutmak ve binlerce "\\" karakterini görsel olarak ayrıştırmaya çalışmak zorunda kalmamak için aşağıdakileri öneriyorum. Bu benim için oldukça iyi çalışıyor gibi görünüyor:

final String regExSpecialChars = "<([{\\^-=$!|]})?*+.>";
final String regExSpecialCharsRE = regExSpecialChars.replaceAll( ".", "\\\\$0");
final Pattern reCharsREP = Pattern.compile( "[" + regExSpecialCharsRE + "]");

String quoteRegExSpecialChars( String s)
{
    Matcher m = reCharsREP.matcher( s);
    return m.replaceAll( "\\\\$0");
}

5

@ Sorin'in Java Kalıp dokümanları önerisine göre, en azından kaçılması gereken karakterler şunlar gibi görünüyor:

\.[{(*+?^$|

4
String escaped = regexString.replaceAll("([\\\\\\.\\[\\{\\(\\*\\+\\?\\^\\$\\|])", "\\\\$1");
fracz

2
)ayrıca kaçılmalıdır ve bir karakter sınıfının içinde veya dışında olmanıza bağlı olarak, kaçacak daha fazla karakter olabilir, bu durumda Pattern.quotekarakter sınıfının hem içinde hem de dışında kullanım için bir dizeden kaçışta oldukça iyi bir iş çıkarır.
nhahtdh

3

Pattern.quote(String s)İstediğin şeyi yapan türden. Ancak arzulanan bir miktar bırakıyor; aslında tek tek karakterlerden kaçmaz, sadece dizeyi\Q...\E .

Tam olarak aradığınızı yapan bir yöntem yoktur, ancak iyi haber şu ki, bir Java normal ifadesindeki tüm özel karakterlerden kaçmak aslında oldukça basittir:

regex.replaceAll("[\\W]", "\\\\$0")

Bu neden işe yarıyor? Belgeleme, Patternözellikle kaçınılması gerekmeyen alfabetik olmayan karakterlerin kaçmasına izin verildiğini söylüyor:

Kaçan bir yapıya işaret etmeyen herhangi bir alfabetik karakterden önce ters eğik çizgi kullanmak bir hatadır; bunlar, normal ifade dilinin gelecekteki uzantıları için ayrılmıştır. Alfabetik olmayan bir karakterden önce, bu karakterin çıkış yapılmamış bir yapının parçası olup olmadığına bakılmaksızın bir ters eğik çizgi kullanılabilir.

Örneğin, ;normal ifadede özel bir karakter değildir. Bunu kaçış Ancak, Patternyine de yorumlayacaktır \;olarak ;. İşte birkaç örnek daha:

  • >\>eşdeğer olan olur>
  • [olur \[ve kaçan formu olan[
  • 8hala 8.
  • \)\\\)kaçan \ve (birleştirilmiş biçimleri haline gelir .

Not: Anahtar, "alfabetik olmayan" ifadesinin tanımıdır ve bu, dokümantasyonda gerçekten " sözcük olmayan " karakterler veya karakter kümesinin dışındaki karakterler anlamına gelir [a-zA-Z_0-9].


2

madalyonun diğer tarafında, uygulama bağlamınızda özel karakterler = allChars - sayı - ABC - boşluk ise, buna benzeyen "karakter olmayan" normal ifadeyi kullanmalısınız.

String regepx = "[^\\s\\w]*";

2

cevap Java için olsa da, kod benim bulduğum Kotlin String uzantısından kolayca uyarlanabilir (sağlanan @brcolow'dan uyarlanmıştır):

private val escapeChars = charArrayOf(
    '<',
    '(',
    '[',
    '{',
    '\\',
    '^',
    '-',
    '=',
    '$',
    '!',
    '|',
    ']',
    '}',
    ')',
    '?',
    '*',
    '+',
    '.',
    '>'
)

fun String.escapePattern(): String {
    return this.fold("") {
      acc, chr ->
        acc + if (escapeChars.contains(chr)) "\\$chr" else "$chr"
    }
}

fun main() {
    println("(.*)".escapePattern())
}

baskılar \(\.\*\)

burada eylem halinde kontrol edin https://pl.kotl.in/h-3mXZkNE


1

Java regex'in kullandığı kaçış karakterleri listesine sahip olduğunuzu ve buna güvendiğinizi (yetkili olmak için) varsayarsak (bu karakterler bazı Desen sınıfı üyelerinde gösterilmiş olsaydı iyi olurdu), gerçekten gerekliyse karakterden kaçmak için aşağıdaki yöntemi kullanabilirsiniz:

private static final char[] escapeChars = { '<', '(', '[', '{', '\\', '^', '-', '=', '$', '!', '|', ']', '}', ')', '?', '*', '+', '.', '>' };

private static String regexEscape(char character) {
    for (char escapeChar : escapeChars) {
        if (character == escapeChar) {
            return "\\" + character;
        }
    }
    return String.valueOf(character);
}
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.