web-dev-qa-db-fra.com

Qu'est-ce qu'une limite de mot dans regex?

J'utilise des expressions rationnelles Java dans Java 1.6 (notamment pour analyser la sortie numérique) et ne trouve pas de définition précise de \b ("limite de mot"). J'avais supposé que -12 serait un "mot entier" (mis en correspondance par \b\-?\d+\b) mais il semble que cela ne fonctionne pas. Je serais reconnaissant de savoir comment faire correspondre des nombres séparés par des espaces.

Exemple:

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

Cela retourne:

true
false
true
84
peter.murray.rust

Une limite de mot, dans la plupart des dialectes d'expression régulière, est une position entre \w et \W (caractère autre que Word), ou au début ou à la fin d'une chaîne si elle commence ou se termine (respectivement) par un caractère Word ([0-9A-Za-z_]).

Ainsi, dans la chaîne "-12", cela correspondrait avant le 1 ou après le 2. Le tiret n'est pas un caractère Word.

70
brianary

Une limite de mot peut apparaître dans l'une des trois positions suivantes:

  1. Avant le premier caractère de la chaîne, si le premier caractère est un caractère Word. 
  2. Après le dernier caractère de la chaîne, si le dernier caractère est un caractère Word.
  3. Entre deux caractères de la chaîne, dont l’un est un caractère Word et l’autre n’est pas un caractère Word. 

Les caractères de mot sont alphanumériques; un signe moins n'est pas . Tiré de Didacticiel Regex .

20
WolfmanDragon

Une limite de mot est une position qui est soit précédée d'un caractère Word et non suivi d'un, soit suivie d'un caractère Word et non précédée d'un.

11
Alan Moore

Je parle de ce que les limites de regex de style \b- sont réellement ici

La nouvelle est qu’ils sont conditionnels. Leur comportement dépend de ce qu’ils côtoient.

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

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

Parfois ce n’est pas ce que vous voulez. Voir mon autre réponse pour plus de détails.

6
tchrist

J'ai rencontré un problème encore plus grave lorsque je cherchais dans le texte des mots tels que .NET, C++, C# et C. On pourrait penser que les programmeurs savent mieux que de nommer une langue pour laquelle il est difficile d'écrire des expressions régulières.

Quoi qu’il en soit, c’est ce que j’ai découvert (résumé principalement de http://www.regular-expressions.info , qui est un site génial): Dans la plupart des goûts de regex, les caractères qui correspondent au raccourci La classe de caractères \w sont les caractères traités comme des caractères Word par les limites de Word. Java est une exception. Java supporte Unicode pour \b mais pas pour \w. (Je suis sûr qu'il y avait une bonne raison pour cela à l'époque).

Le \w signifie "caractère Word". Il correspond toujours aux caractères ASCII [A-Za-z0-9_]. Notez l'inclusion du trait de soulignement et des chiffres (mais pas tiret!). Dans la plupart des versions prenant en charge l’Unicode, \w inclut de nombreux caractères provenant d’autres scripts. Il y a beaucoup d'incohérences quant aux personnages réellement inclus. Les lettres et les chiffres des scripts alphabétiques et des idéogrammes sont généralement inclus. Les signes de ponctuation de connecteur autres que le trait de soulignement et les symboles numériques qui ne sont pas des chiffres peuvent être inclus ou non. XML Schema et XPath incluent même tous les symboles dans \w. Mais Java, JavaScript et PCRE ne font correspondre que les caractères ASCII avec \w.

C'est pourquoi les expressions rationnelles basées sur Java recherchent C++, C# ou .NET (même si vous vous souvenez d'échapper au point et aux plus), sont vissées par le \b.

Remarque: je ne suis pas sûr de savoir quoi faire des erreurs de texte, par exemple, lorsque quelqu'un ne met pas d'espace après un point à la fin d'une phrase. J'ai permis cela, mais je ne suis pas sûr que ce soit nécessairement la bonne chose à faire.

Quoi qu’il en soit, en Java, si vous recherchez du texte pour ces langages nommés de manière étrange, vous devez remplacer le \b par des indicatifs d’espace et de ponctuation avant et après. Par exemple: 

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

Puis dans votre test ou fonction 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));

P.S. Merci à http://regexpal.com/ sans qui le monde des regex serait très misérable!

4
Tihamer

Consultez la documentation sur les conditions aux limites:

http://Java.Sun.com/docs/books/tutorial/essential/regex/bounds.html

Découvrez cet exemple:

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

Lorsque vous l’imprimez, notez que le résultat est le suivant:

[J'ai trouvé la valeur -, dans ma chaîne.]

Cela signifie que le caractère "-" n'est pas considéré comme étant à la limite d'un mot car il n'est pas considéré comme un caractère de mot. On dirait que @brianary m'a un peu battu, alors il obtient un vote positif. 

4
Brent Writes Code

Au cours de l'apprentissage de l'expression régulière, j'étais vraiment coincé dans le métacaractère qui est \b. En effet, je n’en ai pas compris le sens alors que je me demandais "ce que c’est, ce que c’est} _" de manière répétitive. Après quelques tentatives en utilisant le site Web , je surveille les tirets verticaux roses au début et à la fin des mots. Je lui ai bien compris le sens à cette époque. C'est maintenant exactement Word (\w) - frontière.

Mon point de vue est simplement axé sur la compréhension immensément. La logique derrière cela devrait être examinée à partir d'une autre réponse.

 enter image description here

2
snr

Je crois que votre problème est dû au fait que - n'est pas un caractère Word. Ainsi, la limite de mot correspondra après le - et ne le capturera donc pas. Les limites de mot correspondent avant et après les derniers caractères Word d'une chaîne, ainsi qu'à tout endroit où il s'agit avant d'un caractère Word ou d'un caractère autre que Word, et après le contraire. Notez également que la limite de mot est une correspondance de largeur zéro.

Une alternative possible est

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

Cela correspond à tous les nombres commençant par un espace et un tiret facultatif et se terminant par une limite de Word. Cela correspondra également à un numéro commençant au début de la chaîne.

1
Sean

La limite de mot\b est utilisée lorsqu'un mot doit être un caractère Word et un autre, un caractère autre que Word . L'expression régulière d'un nombre négatif doit être

--?\b\d+\b

vérifier travailler D&EACUTE;MO

1
Anubhav Shakya

lorsque vous utilisez \\b(\\w+)+\\b, cela signifie une correspondance exacte avec un mot contenant uniquement des caractères Word ([a-zA-Z0-9]) 

dans votre cas, par exemple, le fait de placer \\b au début de regex acceptera -12 (avec espace), mais là encore il n'acceptera pas -12 (sans espace)

pour référence pour appuyer mes mots: https://docs.Oracle.com/javase/tutorial/essential/regex/bounds.html

0
vic

Je pense que c’est la limite (c’est-à-dire le caractère suivant) de la dernière correspondance ou le début ou la fin de la chaîne.

0
user130076