2013-04-24 11 views
7

Ho un requisito che dice che un nome non deve iniziare con 3 lettere identiche che ignorano il loro caso. Un nome inizia con una lettera maiuscola seguita da lettere minuscole.Come abbinare qualsiasi lettera maiuscola seguita dalla lettera minuscola corrispondente?

Fondamentalmente ho potuto convertire l'intero nome in maiuscolo e quindi corrispondere con un'espressione regolare come (\p{Lu})\1{3,}.*.

Ma mi chiedevo se esiste un'espressione regolare che soddisfa i requisiti precedenti e non richiede alcuna pre-elaborazione della stringa da abbinare. Quindi quale regex posso usare per abbinare stringhe come Aa, Dd o Uu senza specificare esplicitamente alcuna combinazione possibile?

MODIFICA:
Ho accettato la risposta di Markos. Ho solo dovuto sistemarlo per lavorare con i nomi di lunghezza 1 e 2 e ancorarlo all'inizio. Quindi la regex effettiva per il mio caso d'uso è ^(\p{Lu})(\p{Ll}?$|(?=\p{Ll}{2})(?i)(?!(\1){2})).

Ho anche rivalutato le risposte di Evgeniy e sp00m per avermi aiutato a imparare una lezione sulle espressioni regolari.

Grazie per i vostri sforzi.

+0

'(? I) (\ p {Lu}) \ 1 {2,}. *' Non lo farà, ma desidera indicare 2, come una lettera già abbinata. –

risposta

3

Ammetto di aumento su le spalle di giganti (gli altri poster qui), ma questa soluzione funziona davvero per il tuo caso d'uso:

final String[] strings = { "Aba", "ABa", "aba", "aBa", "Aaa", "Aab" }; 
final Pattern p = Pattern.compile("(\\p{Lu})(?=\\p{Ll}{2})(?i)(?!(\\1){2})"); 
for (String s : strings) System.out.println(s + ": " + p.matcher(s).find()); 

Ora abbiamo:

  1. un match per un char upcase anteriore;
  2. un'asserzione lookahead di due caratteri Lowcase seguenti;
  3. un altro aspetto che afferma che questi due caratteri non sono entrambi uguali (ignorando il caso) come primo.

uscita:

Aba: true 
ABa: false 
aba: false 
aBa: false 
Aaa: false 
Aab: true
+0

+1 Questo dovrebbe soddisfare tutti i requisiti richiesti (quando un '. *' Viene aggiunto alla fine) (Non ho letto correttamente la domanda), lo farò non cambiare la mia soluzione ora, dal momento che la tua è molto simile a quello che ho trovato ora. – stema

2

provare

String regex = "(?i)(.)(?=\\p{javaLowerCase})(?<=\\p{javaUpperCase})\\1"; 
    System.out.println("dD".matches(regex)); 
    System.out.println("dd".matches(regex)); 
    System.out.println("DD".matches(regex)); 
    System.out.println("Dd".matches(regex)); 

uscita

false 
false 
false 
true 
+0

Sembra promettente. Inoltre, non riesce ad associare stringhe come 'Dc'. – SpaceTrucker

2

Questo corrisponde a qualsiasi lettera maiuscolo seguita dalla stessa lettera, maiuscolo o no:

([A-Z])(?i)\1 

Questo corrisponde a qualsiasi lettera maiuscolo seguita dalla stessa lettera, ma necessariamente in minuscolo:

([A-Z])(?!\1)(?i)\1 

Ad esempio in Java,

String pattern = "([A-Z])(?!\\1)(?i)\\1"; 
System.out.println("AA".matches(pattern)); 
System.out.println("aa".matches(pattern)); 
System.out.println("aA".matches(pattern)); 
System.out.println("Aa".matches(pattern)); 

stampe

false 
false 
false 
true 
+0

Grazie per questo breve. Ho anche provato e non corrisponde a 'AA'. Inoltre non riesce ad abbinare 'Ab'. – SpaceTrucker

+0

@SpaceTrucker Quindi non ho davvero ottenuto la tua domanda ...Risponde a * "quale espressione regolare posso usare per far corrispondere stringhe come' Aa', 'Dd' o' Uu' senza specificare esplicitamente alcuna combinazione possibile "*. Ma devi anche abbinare 'AA' e' Ab'? – sp00m

+0

L'espressione regolare non deve corrispondere a 'AA'. La tua risposta è corretta per quanto ho provato. – SpaceTrucker

2
soluzione

Evgeniy Dorofeev funziona (+1), ma può essere fatto più semplice, utilizzando solo un lookahead

(\\p{Lu})(?=\\p{Ll})(?i)\\1 

(\\p{Lu}) corrisponde a un carattere maiuscolo e lo memorizza in \\1

(?=\\p{Ll}) è un positive lookahead assertion che assicura che il carattere successivo sia una lettera minuscola.

(?i) è un modificatore in linea che consente la corrispondenza indipendente dal caso.

\\1 corrisponde alla lettera maiuscola della prima parte (ma ora il caso è indipendente a causa del modificatore in primo piano).

prova è:

String[] TestInput = { "foobar", "Aal", "TTest" }; 

Pattern p = Pattern.compile("(\\p{Lu})(?=\\p{Ll})(?i)\\1"); 

for (String t : TestInput) { 
    Matcher m = p.matcher(t); 
    if (m.find()) { 
     System.out.println(t + " ==> " + true); 
    } else { 
     System.out.println(t + " ==> " + false); 
    } 
} 

uscita:

foobar ==> false
Aal ==> true
TEST.T ==> false

+0

Ciò riguarda solo i primi due caratteri (dovrebbe essere tre). Inoltre, non sembra raggiungere il requisito nemmeno per i primi due caratteri: dovrebbe dare true per "Ab" e false per "AB", "ab", "aB" e "Aa". Ma ancora, +1 da parte mia per le buone tecniche, penso che possa essere risolto. –

+0

@stema +1 ora so di \\ p {Ll} –

1

I avere un requisito che dice che un nome non deve iniziare con 3 lettere identiche che ignorano il loro caso.

Si consiglia di utilizzare l'opzione di case-insensitive: (?i)

e il "catch-all" \w esempio: (?i)(\w)\1{2,}.*

o semplicemente [a-z] esempio: (?i)([a-z])\1{2,}.*

0

Potrebbe avere senso qui per utilizzare controlli separati per le diverse esigenze, tanto più che le liste dei requisiti tendono a crescere nel corso del tempo.

per i requisiti descritti sono:

Un nome non deve iniziare con 3 lettere identiche ignorando loro caso

e

Un nome inizia con una lettera maiuscola seguita con lettere minuscole.

L'esecuzione di un controllo separato per ciascuna (come descritto negli altri post) consente inoltre all'utente di fornire all'utente i messaggi di errore corretti che descrivono ciò che è effettivamente sbagliato. Ed è sicuramente più leggibile.

Problemi correlati