Apa itu batas kata dalam regex?

137

Saya menggunakan regex Java di Java 1.6 (untuk mengurai output numerik, antara tujuan lain) dan tidak dapat menemukan definisi yang tepat dari \b("batas kata"). Saya berasumsi bahwa itu -12akan menjadi "kata integer" (cocok dengan \b\-?\d+\b) tetapi tampaknya ini tidak berhasil. Saya akan berterima kasih mengetahui cara-cara mencocokkan angka-angka yang dipisahkan ruang.

Contoh:

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());

Ini mengembalikan:

true
false
true
peter.murray.rust
sumber
Bisakah Anda memposting contoh kecil dengan input dan output yang diharapkan?
Brent Menulis Kode
Contoh 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 ()); memberikan: true false true
peter.murray.rust

Jawaban:

97

Batas kata, dalam sebagian besar dialek regex, adalah posisi antara \wdan \W(karakter non-kata), atau di awal atau akhir string jika dimulai atau diakhiri (masing-masing) dengan karakter kata ( [0-9A-Za-z_]).

Jadi, dalam string "-12", itu akan cocok sebelum 1 atau setelah 2. Tanda hubung bukan karakter kata.

brianary
sumber
35
Correctamundo. \badalah pernyataan nol-lebar yang cocok jika ada \wdi satu sisi, dan ada \Wdi sisi lain atau posisi awal atau akhir string. \wsecara sewenang-wenang didefinisikan sebagai karakter "pengidentifikasi" (alnum dan garis bawah), bukan sebagai sesuatu yang sangat berguna untuk bahasa Inggris.
hobbs
100% benar. Permintaan maaf karena tidak hanya mengomentari Anda. Saya tekan kirim sebelum saya melihat jawaban Anda.
Brent Menulis Kode
5
demi pemahaman, apakah mungkin untuk menulis ulang regex \bhello\btanpa menggunakan \b(menggunakan \w, \Wdan lainnya)?
David Portabella
5
Sortir dari (^|\W)hello($|\W):, kecuali bahwa itu tidak akan menangkap karakter non-kata sebelum dan sesudah, jadi itu akan lebih seperti (^|(?<=\W))hello($|(?=\W))(menggunakan lookahead / lookbehind assertions).
brianary
6
@brianary Sedikit sederhana: (?<!\w)hello(?!\w).
David Knipe
28

Batas kata dapat muncul di salah satu dari tiga posisi:

  1. Sebelum karakter pertama dalam string, jika karakter pertama adalah karakter kata.
  2. Setelah karakter terakhir dalam string, jika karakter terakhir adalah karakter kata.
  3. Antara dua karakter dalam string, di mana satu adalah karakter kata dan yang lainnya bukan karakter kata.

Karakter kata bersifat alfanumerik; tanda minus tidak. Diambil dari Regex Tutorial .

WolfmanDragon
sumber
21

Dalam proses belajar ekspresi reguler, saya benar-benar terjebak dalam metacharacter yang ada \b. Saya memang tidak mengerti artinya ketika saya bertanya pada diri sendiri " apa itu, apa itu " berulang-ulang. Setelah beberapa upaya dengan menggunakan situs web , saya menonton garis vertikal merah muda di setiap awal kata dan di akhir kata. Saya mengerti artinya pada saat itu. Sekarang persis kata ( \w) -batas .

Pandangan saya hanya berorientasi pada pemahaman. Logika di balik itu harus diperiksa dari jawaban lain.

masukkan deskripsi gambar di sini

snr
sumber
3
Situs yang sangat bagus untuk memahami apa itu batas kata dan bagaimana kecocokan terjadi
vsingh
2
Pos ini layak mendapat pujian karena menunjukkan alih-alih memberi tahu. Sebuah gambar bernilai ribuan kata.
M_M
13

Batas kata adalah posisi yang didahului oleh karakter kata dan tidak diikuti oleh kata, atau diikuti oleh karakter kata dan tidak didahului oleh karakter.

Alan Moore
sumber
8

Saya berbicara tentang apa- \bbatas gaya regex sebenarnya di sini .

Cerpennya adalah bahwa mereka bersyarat . Perilaku mereka tergantung pada apa yang akan mereka lakukan selanjutnya.

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

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

Terkadang bukan itu yang Anda inginkan. Lihat jawaban saya yang lain untuk penjelasan.

tchrist
sumber
8

Saya ingin menjelaskan jawaban Alan Moore

Batas kata adalah posisi yang didahului oleh karakter kata dan tidak diikuti oleh satu atau diikuti oleh karakter kata dan tidak didahului oleh satu.

Misalkan saya punya string "Ini adalah sebuah c sebuah t, dan dia seorang wesome", dan saya seharusnya untuk mengganti semua kejadian (s) huruf 'a' hanya jika surat ini ada di "Batas dari sebuah kata" , yaitu huruf adi dalam 'cat' tidak boleh diganti.

Jadi saya akan melakukan regex (dengan Python ) sebagai

re.sub("\ba","e", myString.strip())// ganti adengane

sehingga output akan ini adalah ec sebuah t end dia ini ewesome

Daksh Gargas
sumber
5

Aku berlari ke masalah lebih buruk ketika mencari teks untuk kata-kata seperti .NET, C++, C#, dan C. Anda akan berpikir bahwa pemrogram komputer akan tahu lebih baik daripada memberi nama bahasa sesuatu yang sulit untuk menulis ekspresi reguler.

Bagaimanapun, ini adalah apa yang saya temukan (dirangkum sebagian besar dari http://www . regular-expressions.info , yang merupakan situs yang hebat): Dalam kebanyakan rasa regex, karakter yang cocok dengan kelas karakter tangan pendek \wadalah karakter yang diperlakukan sebagai karakter kata dengan batas kata. Java adalah pengecualian. Java mendukung Unicode untuk \btetapi tidak untuk \w. (Saya yakin ada alasan bagus untuk itu pada saat itu).

The \wsingkatan dari "karakter kata". Itu selalu cocok dengan karakter ASCII [A-Za-z0-9_]. Perhatikan dimasukkannya garis bawah dan digit (tetapi tidak putus-putus!). Dalam sebagian besar rasa yang mendukung Unicode, \wsertakan banyak karakter dari skrip lain. Ada banyak ketidakkonsistenan tentang karakter mana yang sebenarnya dimasukkan. Huruf dan angka dari skrip alfabet dan ideograf umumnya disertakan. Tanda baca konektor selain simbol garis bawah dan angka yang bukan digit mungkin atau mungkin tidak disertakan. Skema XML dan XPath bahkan menyertakan semua simbol di \w. Tetapi Java, JavaScript, dan PCRE hanya cocok dengan karakter ASCII \w.

Itulah sebabnya pencarian regex berbasis Java untuk C++, C#atau .NET(bahkan ketika Anda ingat untuk keluar dari periode dan plus) dikacaukan oleh \b.

Catatan: Saya tidak yakin apa yang harus dilakukan tentang kesalahan dalam teks, seperti ketika seseorang tidak memberi spasi setelah periode di akhir kalimat. Saya mengizinkannya, tetapi saya tidak yakin itu hal yang tepat untuk dilakukan.

Bagaimanapun, di Jawa, jika Anda mencari teks untuk bahasa-bahasa aneh, Anda harus mengganti \bdengan sebelum dan sesudah spasi putih dan tanda baca. Sebagai contoh:

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();
}

Kemudian dalam tes atau fungsi utama Anda:

    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));

PS Terima kasih saya kepada http://regexpal.com/ tanpa siapa dunia regex akan sangat menyedihkan!

Tihamer
sumber
Saya berusaha keras untuk memahami mengapa saya tidak bisa menyamai C#tetapi sekarang lebih jelas
Mugoma J. Okomba
4

Lihat dokumentasi tentang syarat batas:

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

Lihat contoh ini:

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")));
    }

Ketika Anda mencetaknya, perhatikan bahwa hasilnya adalah ini:

[Saya menemukan nilai -, dalam string saya.]

Ini berarti bahwa karakter "-" tidak diambil sebagai berada pada batas kata karena itu tidak dianggap sebagai karakter kata. Sepertinya @brianary agak mengalahkan saya, jadi dia mendapat suara.

Brent Menulis Kode
sumber
2

Batas kata \ b digunakan di mana satu kata harus berupa karakter kata dan yang lain merupakan karakter non-kata. Ekspresi Reguler untuk angka negatif seharusnya

--?\b\d+\b

periksa DEMO yang berfungsi

Anubhav Shakya
sumber
1

Saya percaya bahwa masalah Anda disebabkan oleh fakta bahwa -bukan karakter kata. Dengan demikian, kata batas akan cocok setelah -, dan dengan demikian tidak akan menangkapnya. Batas kata cocok sebelum karakter kata pertama dan setelah kata terakhir dalam sebuah string, serta tempat di mana sebelumnya adalah karakter kata atau karakter non-kata, dan setelah itu adalah kebalikannya. Perhatikan juga bahwa batas kata adalah kecocokan dengan lebar nol.

Salah satu alternatif yang mungkin adalah

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

Ini akan cocok dengan angka apa pun yang dimulai dengan karakter spasi dan tanda hubung opsional, dan berakhir pada batas kata. Ini juga akan cocok dengan angka yang dimulai pada awal string.

Sean
sumber
0

Saya pikir itu adalah batas (yaitu karakter yang mengikuti) dari pertandingan terakhir atau awal atau akhir dari string.


sumber
1
Anda sedang memikirkan \G: cocok dengan awal string (seperti \A) pada upaya pertandingan pertama; setelah itu cocok dengan posisi di mana pertandingan sebelumnya berakhir.
Alan Moore
0

ketika Anda menggunakan \\b(\\w+)+\\bitu berarti sama persis dengan kata yang hanya mengandung karakter kata([a-zA-Z0-9])

dalam kasus Anda misalnya pengaturan \\bpada awal regex akan menerima -12(dengan spasi) tetapi sekali lagi itu tidak akan menerima -12(tanpa spasi)

untuk referensi untuk mendukung kata-kata saya: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html

vic
sumber