Pattern Matching negli archi in Groovy

1. Panoramica

In questo articolo, esamineremo le funzionalità del linguaggio Groovy per la corrispondenza dei pattern in Strings.

Vedremo come l'approccio di Groovy con batterie incluse ci fornisce una sintassi potente ed ergonomica per le nostre esigenze di base di pattern matching.

2. Operatore di pattern

Il linguaggio Groovy introduce il cosiddetto operatore pattern ~ . Questo operatore può essere considerato una scorciatoia sintattica di zucchero per il metodo java.util.regex.Pattern.compile (stringa) di Java .

Vediamolo in pratica come parte di un test di Spock :

def "pattern operator example"() { given: "a pattern" def p = ~'foo' expect: p instanceof Pattern and: "you can use slashy strings to avoid escaping of blackslash" def digitPattern = ~/\d*/ digitPattern.matcher('4711').matches() }

Anche questo è abbastanza conveniente, ma vedremo che questo operatore è semplicemente la linea di base per alcuni altri operatori ancora più utili.

3. Operatore di corrispondenza

La maggior parte delle volte, e specialmente durante la scrittura di test, non siamo veramente interessati a creare oggetti Pattern , ma invece, vogliamo controllare se una stringa corrisponde a una certa espressione regolare (o Pattern ). Groovy, quindi, contiene anche l'operatore di corrispondenza == ~ .

Restituisce un valore booleano ed esegue una corrispondenza rigorosa con l'espressione regolare specificata. Fondamentalmente, è una scorciatoia sintattica sulla chiamata di Pattern.matches (regex, stringa) .

Di nuovo, lo esamineremo in pratica come parte di un test di Spock :

def "match operator example"() { expect: 'foobar' ==~ /.*oba.*/ and: "matching is strict" !('foobar' ==~ /foo/) }

4. Trova operatore

L'ultimo operatore Groovy nel contesto del pattern matching è l'operatore find ~ = . In questo caso, l'operatore creerà e restituirà direttamente un'istanza java.util.regex.Matcher .

Possiamo agire su questa istanza Matcher , ovviamente, accedendo ai suoi metodi API Java conosciuti. Ma in aggiunta, siamo anche in grado di accedere a gruppi abbinati utilizzando un array multidimensionale.

E non è tutto: l' istanza Matcher forzerà automaticamente un tipo booleano chiamando il suo metodo find () se usato come predicato. Citando la documentazione ufficiale di Groovy, questo significa che "l'operatore = ~ è coerente con il semplice utilizzo dell'operatore = ~ di Perl".

Qui vediamo l'operatore in azione:

def "find operator example"() { when: "using the find operator" def matcher = 'foo and bar, baz and buz' =~ /(\w+) and (\w+)/ then: "will find groups" matcher.size() == 2 and: "can access groups using array" matcher[0][0] == 'foo and bar' matcher[1][2] == 'buz' and: "you can use it as a predicate" 'foobarbaz' =~ /bar/ }

5. conclusione

Abbiamo visto come il linguaggio Groovy ci dia accesso alle funzionalità Java integrate per quanto riguarda le espressioni regolari in un modo molto conveniente.

La documentazione ufficiale di Groovy contiene anche alcuni esempi concisi riguardo a questo argomento. È particolarmente interessante se si considera che gli esempi di codice nei documenti vengono eseguiti come parte della compilazione della documentazione.

Come sempre, è possibile trovare esempi di codice su GitHub.