Cos'è una parola limite in regex?


137

Sto usando regex Java in Java 1.6 (per analizzare l'output numerico, tra gli altri scopi) e non riesco a trovare una definizione precisa di \b("confine di parole"). Avevo supposto che -12sarebbe stata una "parola intera" (corrispondente a \b\-?\d+\b) ma sembra che non funzioni. Sarei grato di sapere come abbinare i numeri separati da spazio.

Esempio:

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

Questo ritorna:

true
false
true

Puoi pubblicare un piccolo esempio con input e output previsti?
Brent scrive il codice il

Esempio Pattern pattern = Pattern.compile ("\\ s * \\ b \\ -? \\ d + \\ s *"); String plus = "12"; System.out.println ( "" + pattern.matcher (più) .matches ()); String meno = "-12"; System.out.println ( "" + pattern.matcher (meno) .matches ()); pattern = Pattern.compile ("\\ s * \\ -? \\ d + \\ s *"); System.out.println ( "" + pattern.matcher (meno) .matches ()); dà: vero falso vero
peter.murray.rust

Risposte:


97

Un limite di parole, nella maggior parte dei dialetti regex, è una posizione tra \we \W(carattere non verbale), o all'inizio o alla fine di una stringa se inizia o termina (rispettivamente) con un carattere parola ( [0-9A-Za-z_]).

Quindi, nella stringa "-12", corrisponderebbe prima dell'1 o dopo il 2. Il trattino non è un carattere di parola.


35
Correctamundo. \bè un'asserzione di larghezza zero che corrisponde se esiste \wda un lato e c'è \Wdall'altro o se la posizione è all'inizio o alla fine della stringa. \wviene arbitrariamente definito come carattere "identificativo" (alnum e trattino basso), non come qualcosa di particolarmente utile per l'inglese.
Hobbs,

100% corretto. Mi scuso non solo per commentare il tuo. Ho premuto Invia prima di vedere la tua risposta.
Brent scrive il codice il

5
per agevolare la comprensione, è possibile riscrivere la regex \bhello\bsenza usare \b(usando \w, \We altri)?
David Portabella,

5
Sorta di :, (^|\W)hello($|\W)tranne per il fatto che non catturerebbe alcun carattere senza parole prima e dopo, quindi sarebbe più simile (^|(?<=\W))hello($|(?=\W))(usando asserzioni lookahead / lookbehind).
brianary

6
@brianary leggermente più semplice: (?<!\w)hello(?!\w).
David Knipe,

28

Un limite di parole può verificarsi in una di tre posizioni:

  1. Prima del primo carattere nella stringa, se il primo carattere è una parola.
  2. Dopo l'ultimo carattere nella stringa, se l'ultimo carattere è una parola.
  3. Tra due caratteri nella stringa, dove uno è un carattere di parola e l'altro non è un carattere di parola.

I caratteri delle parole sono alfanumerici; un segno meno non lo è. Tratto da Regex Tutorial .


21

Nel corso dell'apprendimento dell'espressione regolare, ero davvero bloccato nel metacarattere che è \b. In effetti non ho capito il suo significato mentre mi chiedevo " cos'è, cosa è " ripetutamente. Dopo alcuni tentativi utilizzando il sito Web , guardo i trattini verticali rosa all'inizio di ogni parola e alla fine delle parole. L'ho capito bene in quel momento. Ora è esattamente word ( \w) -boundary .

La mia visione è semplicemente orientata alla comprensione immensamente. La logica dietro di essa dovrebbe essere esaminata da un'altra risposta.

inserisci qui la descrizione dell'immagine


3
Un ottimo sito per capire cosa sia un limite di parole e come stanno avvenendo le partite
vsingh

2
Questo post merita credito per essere mostrato invece di dirlo. Un'immagine vale più di mille parole.
M_M

13

Il limite di una parola è una posizione preceduta da un carattere di parola e non seguita da uno, oppure seguita da un carattere di parola e non preceduta da uno.


8

Parlo di quello che \bi confini in stile regex in realtà sono qui .

Il racconto è che sono condizionati . Il loro comportamento dipende da cosa stanno accanto.

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

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

A volte non è quello che vuoi. Vedi la mia altra risposta per l'elaborazione.


8

Vorrei spiegare la risposta di Alan Moore

Il limite di una parola è una posizione preceduta da un carattere di parola e non seguita da uno o seguita da un carattere di parola e non preceduta da uno.

Supponiamo di avere una stringa "This is a c a t, and is a wesome", e dovrei sostituire tutte le occorrenze con la lettera "a" solo se questa lettera esiste al "Confine di una parola" , cioè la letteraa all'interno di 'cat' non dovrebbe essere sostituita.

Quindi eseguirò regex (in Python ) come

re.sub("\ba","e", myString.strip())// sostituisci acone

quindi l'uscita sarà Questo è ec una T e° di lei ewesome


5

Mi sono imbattuto in un problema ancora peggio quando la ricerca di testo per parole come .NET, C++, C#, eC . Penseresti che i programmatori di computer saprebbero meglio che nominare una lingua per cui è difficile scrivere espressioni regolari.

Ad ogni modo, questo è quello che ho scoperto (riassunto principalmente da http://www.regular-expressions.info , che è un ottimo sito): nella maggior parte dei gusti di regex, i personaggi che corrispondono alla classe dei caratteri a mano corta \wsono i caratteri che sono trattati come caratteri di parola dai limiti di parola. Java è un'eccezione. Java supporta Unicode per \bma non per \w. (Sono sicuro che ci fosse una buona ragione per farlo al momento).

La \wsta per "carattere di parola". Corrisponde sempre ai caratteri ASCII [A-Za-z0-9_]. Notare l'inclusione del trattino basso e delle cifre (ma non trattino!). Nella maggior parte dei gusti che supportano Unicode, \winclude molti caratteri di altri script. C'è molta incoerenza su quali personaggi siano effettivamente inclusi. Sono generalmente incluse lettere e cifre di script alfabetici e ideografi. La punteggiatura del connettore diversa dal carattere di sottolineatura e dai simboli numerici che non sono cifre può o meno essere inclusa. XML Schema e XPath includono anche tutti i simboli in \w. Ma Java, JavaScript e PCRE corrispondono solo a caratteri ASCII con \w.

Quale è il motivo per Java-based ricerche regex per C++, C#o .NET(anche quando si ricorda di fuggire il periodo e vantaggi) sono avvitati dal \b.

Nota: non sono sicuro di cosa fare per gli errori nel testo, come quando qualcuno non mette uno spazio dopo un punto alla fine di una frase. L'ho permesso, ma non sono sicuro che sia necessariamente la cosa giusta da fare.

Ad ogni modo, in Java, se stai cercando del testo per quei linguaggi dai \bnomi strani, devi sostituire quelli con spazi bianchi prima e dopo e i designatori di punteggiatura. Per esempio:

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

Quindi nel test o nella funzione principale:

    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 I miei ringraziamenti a http://regexpal.com/ senza i quali il mondo regex sarebbe davvero infelice!


Ho faticato a cercare di capire perché non potevo eguagliarmi, C#ma ora è più chiaro
Mugoma J. Okomba il

4

Consulta la documentazione sulle condizioni al contorno:

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

Dai un'occhiata a questo esempio:

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

Quando lo stampi, nota che l'output è questo:

[Ho trovato il valore -, nella mia stringa.]

Ciò significa che il carattere "-" non viene preso come al limite di una parola perché non è considerato un carattere di parola. Sembra che @brianary mi abbia battuto un pò, quindi ottiene un voto positivo.


2

Il limite di parole \ b viene utilizzato dove una parola dovrebbe essere un carattere di parola e un'altra un carattere non di parole. L'espressione regolare per il numero negativo dovrebbe essere

--?\b\d+\b

controlla DEMO funzionante


1

Credo che il tuo problema sia dovuto al fatto che -non è una parola personaggio. Pertanto, la parola limite corrisponderà dopo il -, e quindi non la catturerà. I confini delle parole corrispondono prima del primo e dopo l'ultimo carattere di una stringa, così come in qualsiasi altro punto in cui prima è un carattere di parola o non di parola, e dopo è l'opposto. Si noti inoltre che il limite di parole è una corrispondenza di larghezza zero.

Una possibile alternativa è

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

Ciò corrisponderà a tutti i numeri che iniziano con un carattere spazio e un trattino opzionale e terminano con un limite di parole. Abbinerà anche un numero che inizia all'inizio della stringa.


0

Penso che sia il limite (cioè il carattere che segue) dell'ultima partita o l'inizio o la fine della stringa.


1
Stai pensando a \G: corrisponde all'inizio della stringa (come \A) al primo tentativo di corrispondenza; successivamente corrisponde alla posizione in cui è terminata la partita precedente.
Alan Moore,

0

quando lo usi \\b(\\w+)+\\bsignifica che corrisponde esattamente a una parola contenente solo caratteri di parole([a-zA-Z0-9])

nel tuo caso, ad esempio, l'impostazione \\ball'inizio di regex accetterà -12(con spazio) ma di nuovo non accetterà -12(senza spazio)

come riferimento per supportare le mie parole: https://docs.oracle.com/javase/tutorial/essential/regex/bounds.html

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.