mi sono imbattuto in un problema ancora peggio quando la ricerca di testo per parole come .NET
, C++
, C#
e C
. Si potrebbe pensare che i programmatori di computer saprebbero meglio che nominare un linguaggio per cui è difficile scrivere espressioni regolari.
Comunque, questo è quello che ho scoperto (riassunto per lo più da http://www.regular-expressions.info, che è un ottimo sito): Nella maggior parte dei sapori della regex, personaggi che è compensata dalla classe del personaggio a breve mano \w
sono i personaggi che sono trattati come parola caratteri per parola. Java è un'eccezione. Java supporta Unicode per \b
ma non per \w
. (Sono sicuro che c'era una buona ragione per questo in quel momento).
\w
indica "carattere parola". Corrisponde sempre ai caratteri ASCII [A-Za-z0-9_]
. Notare l'inclusione del carattere di sottolineatura e delle cifre (ma non il trattino!). Nella maggior parte dei gusti che supportano Unicode, \w
include molti caratteri di altri script. C'è molta incongruenza su quali personaggi sono effettivamente inclusi. Sono generalmente incluse lettere e cifre di script alfabetici e ideogrammi. La punteggiatura del connettore diversa dal carattere di sottolineatura e dai simboli numerici che non sono cifre potrebbe essere inclusa o meno. XML Schema e XPath includono anche tutti i simboli in \w
. Ma Java, JavaScript e PCRE corrispondono solo caratteri ASCII con \w
.
Ecco perché basata su Java ricerche regex per C++
, C#
o .NET
(anche quando si ricorda di fuggire il periodo e vantaggi) sono avvitate dal \b
.
Nota: non sono sicuro di cosa fare per errori di 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 si cercano testi per quelle lingue con nomi strani, è necessario sostituire lo \b
con i designatori di spazi bianchi e punteggiatura prima e dopo. 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();
}
Poi, nel tuo test o 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));
P.S. I miei ringraziamenti allo http://regexpal.com/ senza il quale il mondo delle regex sarebbe molto miserabile!
Puoi pubblicare un piccolo esempio con ingresso e uscita prevista? –
Proverà a costruire uno –
Esempio \t Pattern pattern = Pattern.compile ("\\ s * \\ b \\ -? \\ d + \\ s *"); \t Stringa più = "12"; \t System.out.println ("" + pattern.matcher (plus) .matches()); \t Stringa meno = "-12"; \t System.out.println ("" + pattern.matcher (meno) .matches()); \t pattern = Pattern.compile ("\\ s * \\ -? \\ d + \\ s *"); \t System.out.println ("" + pattern.matcher (meno) .matches()); corrisponde a true false true –