Normal ifadede kelime sınırı nedir?


138

Java 1.6'da Java regexes kullanıyorum (diğer amaçların yanı sıra sayısal çıktıyı ayrıştırmak için) ve \b("kelime sınırı") nın kesin bir tanımını bulamıyorum . Bunun -12bir "tam sayı kelimesi" (ile eşleşen \b\-?\d+\b) olacağını varsaydım, ancak bu işe yaramıyor gibi görünüyor. Boşluklarla ayrılmış sayıları eşleştirmenin yollarını bildiğim için minnettar olurum.

Misal:

Pattern pattern = Pattern.compile("\\s*\\b\\-?\\d+\\s*");
String plus = " 12 ";
System.out.println(""+pattern.matcher(plus).matches());
String minus = " -12 ";
System.out.println(""+pattern.matcher(minus).matches());
pattern = Pattern.compile("\\s*\\-?\\d+\\s*");
System.out.println(""+pattern.matcher(minus).matches());

Bu şunu döndürür:

true
false
true

Girdi ve beklenen çıktıyla küçük bir örnek gönderebilir misiniz?
Brent Kod Yazıyor

Örnek Kalıp kalıbı = Kalıp.compile ("\\ s * \\ b \\ -? \\ d + \\ s *"); Dize artı = "12"; System.out.println ( "" + pattern.matcher (artı) .matches ()); Dize eksi = "-12"; System.out.println ( "" + pattern.matcher (eksi) .matches ()); desen = Pattern.compile ("\\ s * \\ -? \\ d + \\ s *"); System.out.println ( "" + pattern.matcher (eksi) .matches ()); verir: doğru yanlış doğru
peter.murray.rust

Yanıtlar:


98

Sözcük sınırı, çoğu normal ifade lehçesinde, \wve \W(sözcük olmayan) arasında veya bir sözcük karakteriyle ( [0-9A-Za-z_]) başlıyorsa veya bitiyorsa (sırasıyla) bir dizenin başında veya sonundaki bir konumdur .

Dolayısıyla, dizede "-12"1'den önce veya 2'den sonra eşleşir. Kısa çizgi bir kelime karakteri değildir.


35
Correctamundo. bir tarafta varsa ve diğer tarafta varsa veya konum dizenin başlangıcı veya \bsonuysa eşleşen sıfır genişlikli bir iddiadır . "tanımlayıcı" karakterler (alt çizgi ve alt çizgi) olarak rastgele tanımlanır, özellikle İngilizce için yararlı bir şey değildir. \w\W\w
hobbs

% 100 doğru. Sizinkine yorum yapmadığınız için özür dileriz. Cevabınızı görmeden gönder düğmesine bastım.
Brent Kod Yazıyor

5
anlayış uğruna, bu regex yeniden yazmak mümkündür \bhello\bkullanmadan \b(kullanarak \w, \Wve diğer)?
David Portabella

5
Sırala:, (^|\W)hello($|\W)önceki ve sonraki sözcük olmayan karakterleri yakalaması dışında, daha çok (^|(?<=\W))hello($|(?=\W))(ileri / geriye bakma iddialarını kullanarak).
brianary

7
Biraz daha basit @brianary: (?<!\w)hello(?!\w).
David Knipe

28

Üç konumdan birinde bir sözcük sınırı oluşabilir:

  1. İlk karakter bir kelime karakteriyse, dizedeki ilk karakterden önce.
  2. Dizedeki son karakterden sonra, son karakter bir kelime karakteriyse.
  3. Birinin kelime karakteri ve diğerinin kelime karakteri olmadığı dizedeki iki karakter arasında.

Kelime karakterleri alfa sayısaldır; eksi işareti değildir. Alındığı Regex Öğreticisi .


21

Düzenli ifadeyi öğrenirken, gerçekten meta karaktere takılı kaldım \b. Gerçekten de kendime tekrar tekrar " nedir, ne? " Diye sorarken anlamını anlamadım . Web sitesini kullanarak birkaç denemeden sonra , kelimelerin her başında ve kelimelerin sonundaki pembe dikey çizgilere dikkat ediyorum. O zaman anlamını iyi anladım. Artık tam olarak kelime ( \w) -sınır .

Benim görüşüm sadece son derece anlayış odaklı. Arkasındaki mantık başka cevaplardan incelenmelidir.

görüntü açıklamasını buraya girin


3
Kelime sınırının ne olduğunu ve eşleşmelerin nasıl olduğunu anlamak için çok iyi bir site
vsingh

2
Bu gönderi, anlatmak yerine gösterdiği için övgüyü hak ediyor. Bir resim bin kelimeye bedeldir.
M_M

13

Kelime sınırı, ya bir kelime karakterinin önünde olan ve onu takip etmeyen ya da bir kelime karakteri takip eden ve önünde bir gelmeyen bir konumdur.


8

Hangi \btarzdaki normal ifade sınırlarının aslında burada olduğundan bahsediyorum .

Kısa hikaye, şartlı olmalarıdır . Davranışları, yanında ne olduklarına bağlıdır.

# same as using a \b before:
(?(?=\w) (?<!\w)  | (?<!\W) )

# same as using a \b after:
(?(?<=\w) (?!\w)  | (?!\W)  )

Bazen istediğin bu değil. Ayrıntılı bilgi için diğer cevabıma bakın.


8

Alan Moore'un cevabını açıklamak isterim

Kelime sınırı, ya bir kelime karakterinin önünde olan ve ardından bir kelime karakteri gelmeyen ya da bir kelime karakteri takip eden ve önünde bir karakter gelmeyen bir konumdur.

Diyelim ki "Bu bir c a t ve o bir harika" dizesi var ve tüm oluşum (lar) ı, yalnızca bu harf "bir kelimenin sınırında" varsa " a " harfini değiştirmem gerekiyor , yani a'kedi' içindeki harf değiştirilmemelidir.

Bu yüzden ( Python'da ) normal ifadeyi şu şekilde gerçekleştireceğim:

re.sub("\ba","e", myString.strip())yerine // ailee

çıkış olacak böylece budur ec bir t end Kız ewesome


5

Kelimeler gibi metnini ararken ben bir daha da kötüsü sorun koştu .NET, C++, C#, ve C. Bilgisayar programcılarının, bir dile düzenli ifadeler yazması zor bir şeyi adlandırmaktan daha iyi bileceğini düşünürsünüz.

Her neyse, öğrendiğim şey buydu (çoğunlukla harika bir site olan http: //www.regular-expressions.info'dan özetlenmiştir ): Çoğu normal ifade çeşidinde, kısa el karakter sınıfıyla eşleşen karakterler \wşunlardır: kelime sınırlarına göre kelime karakterleri olarak değerlendirilen karakterler. Java bir istisnadır. Java, Unicode'u destekler, \bancak için desteklemez \w. (Eminim o sırada bunun iyi bir nedeni vardır).

\w"Kelime karakteri" anlamına gelir. Her zaman ASCII karakterleriyle eşleşir [A-Za-z0-9_]. Alt çizgi ve rakamların eklendiğine dikkat edin (ancak tire değil!). Unicode'u destekleyen çoğu tatta \w, diğer komut dosyalarından birçok karakter bulunur. Gerçekte hangi karakterlerin dahil edildiği konusunda pek çok tutarsızlık var. Alfabetik yazılardan ve ideograflardan gelen harfler ve rakamlar genellikle dahil edilir. Rakam olmayan alt çizgi ve sayısal semboller dışındaki bağlayıcı noktalama işaretleri dahil edilebilir veya edilmeyebilir. XML Şeması ve XPath tüm sembolleri \w. Ancak Java, JavaScript ve PCRE yalnızca ASCII karakterleriyle eşleşir \w.

İçin regex aramalar Java tabanlı yüzden hangisi C++, C#ya .NET(eğer süresi ve artılar kaçmayı unutmayın bile) tarafından vidalanır \b.

Not: Birisinin cümlenin sonunda bir noktadan sonra boşluk bırakmaması gibi, metindeki hatalar konusunda ne yapacağımı bilmiyorum. Buna izin verdim, ancak bunun mutlaka yapılacak doğru şey olduğundan emin değilim.

Her neyse, Java'da, tuhaf adlandırılmış diller için metin arıyorsanız, \bbeyaz boşluk ve noktalama işaretçilerinden önce ve sonra yazmanız gerekir . Örneğin:

public static String grep(String regexp, String multiLineStringToSearch) {
    String result = "";
    String[] lines = multiLineStringToSearch.split("\\n");
    Pattern pattern = Pattern.compile(regexp);
    for (String line : lines) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            result = result + "\n" + line;
        }
    }
    return result.trim();
}

Ardından testinizde veya ana işlevinizde:

    String beforeWord = "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|^)";   
    String afterWord =  "(\\s|\\.|\\,|\\!|\\?|\\(|\\)|\\'|\\\"|$)";
    text = "Programming in C, (C++) C#, Java, and .NET.";
    System.out.println("text="+text);
    // Here is where Java word boundaries do not work correctly on "cutesy" computer language names.  
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for .NET="+ grep("\\b\\.NET\\b", text));
    System.out.println("Should find: grep exactly for .NET="+ grep(beforeWord+"\\.NET"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java: grep with word boundary for C#="+ grep("\\bC#\\b", text));
    System.out.println("Should find: grep exactly for C#="+ grep("C#"+afterWord, text));
    System.out.println("Bad word boundary can't find because of Java:grep with word boundary for C++="+ grep("\\bC\\+\\+\\b", text));
    System.out.println("Should find: grep exactly for C++="+ grep(beforeWord+"C\\+\\+"+afterWord, text));

    System.out.println("Should find: grep with word boundary for Java="+ grep("\\bJava\\b", text));
    System.out.println("Should find: grep for case-insensitive java="+ grep("?i)\\bjava\\b", text));
    System.out.println("Should find: grep with word boundary for C="+ grep("\\bC\\b", text));  // Works Ok for this example, but see below
    // Because of the stupid too-short cutsey name, searches find stuff it shouldn't.
    text = "Worked on C&O (Chesapeake and Ohio) Canal when I was younger; more recently developed in Lisp.";
    System.out.println("text="+text);
    System.out.println("Bad word boundary because of C name: grep with word boundary for C="+ grep("\\bC\\b", text));
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));
    // Make sure the first and last cases work OK.

    text = "C is a language that should have been named differently.";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    text = "One language that should have been named differently is C";
    System.out.println("text="+text);
    System.out.println("grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

    //Make sure we don't get false positives
    text = "The letter 'c' can be hard as in Cat, or soft as in Cindy. Computer languages should not require disambiguation (e.g. Ruby, Python vs. Fortran, Hadoop)";
    System.out.println("text="+text);
    System.out.println("Should be blank: grep exactly for C="+ grep(beforeWord+"C"+afterWord, text));

Not: http://regexpal.com/ 'a teşekkürler, kim olmadan regex dünyası çok perişan olurdu!


Neden eşleşemediğimi anlamaya çalışırken C#
zorlandım

4

Sınır koşullarıyla ilgili belgeleri inceleyin:

http://java.sun.com/docs/books/tutorial/essential/regex/bounds.html

Bu örneğe göz atın:

public static void main(final String[] args)
    {
        String x = "I found the value -12 in my string.";
        System.err.println(Arrays.toString(x.split("\\b-?\\d+\\b")));
    }

Yazdırdığınızda çıktının şu olduğuna dikkat edin:

[Dizimde - değerini buldum.]

Bu, "-" karakterinin, bir kelime karakteri olarak kabul edilmediğinden, bir kelimenin sınırında olarak algılanmadığı anlamına gelir. Görünüşe göre @brianary beni yumruk attı, bu yüzden oy kullanacak.


2

Sözcük sınırı \ b, bir sözcüğün sözcük karakteri ve diğerinin sözcük olmayan bir karakter olması gerektiğinde kullanılır. Negatif sayı için Normal İfade olmalıdır

--?\b\d+\b

çalışan DEMO'yu kontrol et


1

Senin sorununun -bir kelime karakteri olmamasından kaynaklandığına inanıyorum . Bu nedenle, kelime sınırı, 'den sonra eşleşecek -ve dolayısıyla onu yakalayamayacaktır. Sözcük sınırları, bir dizedeki ilk ve son sözcük karakterlerinden önce ve son sözcük karakterlerinden önce ve ayrıca bir sözcük karakteri veya sözcük olmayan karakterden önce ve sonra tam tersi olan herhangi bir yerle eşleşir. Ayrıca, kelime sınırının sıfır genişlikli bir eşleşme olduğunu unutmayın.

Olası bir alternatif şudur:

(?:(?:^|\s)-?)\d+\b

Bu, bir boşluk karakteri ve isteğe bağlı bir tire ile başlayan ve bir kelime sınırında biten tüm sayılarla eşleşecektir. Ayrıca dizenin başından başlayan bir sayıyla da eşleşecektir.


0

Sanırım bu, son eşleşmenin sınırı (yani karakter izleyen) veya dizenin başlangıcı veya sonu.


1
Düşünüyorsunuz \G: \Ailk eşleşme denemesinde dizenin başlangıcıyla eşleşir (benzer ); bundan sonra önceki maçın bittiği pozisyonla eşleşir.
Alan Moore

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.