Ricerca…
Idiomi per la corrispondenza di Regex in When Expression
Usando i locali immutabili:
Utilizza meno spazio orizzontale ma più spazio verticale rispetto al modello "anonymous temporaries". Preferibile sul modello "anonymous temporaries" se l'espressione when
è in un loop - in questo caso, le definizioni regex devono essere posizionate all'esterno del ciclo.
import kotlin.text.regex
var string = /* some string */
val regex1 = Regex( /* pattern */ )
val regex2 = Regex( /* pattern */ )
/* etc */
when {
regex1.matches(string) -> /* do stuff */
regex2.matches(string) -> /* do stuff */
/* etc */
}
Usando i temporari anonimi:
Utilizza meno spazio verticale ma più spazio orizzontale rispetto al modello "immutabili locali". Non dovrebbe essere usato se poi when
espressione è in un ciclo.
import kotlin.text.regex
var string = /* some string */
when {
Regex( /* pattern */ ).matches(string) -> /* do stuff */
Regex( /* pattern */ ).matches(string) -> /* do stuff */
/* etc */
}
Utilizzando il modello di visitatore:
Ha il vantaggio di emulare da vicino il "argument-ful" when
sintassi. Ciò è utile perché indica più chiaramente l'argomento dell'espressione when
, e preclude anche alcuni errori del programmatore che potrebbero derivare dal dover ripetere l'argomento when
in ogni whenEntry
. O il modello "immutable locals" o "anonymous temporaries" può essere utilizzato con questa implementazione del pattern visitor.
import kotlin.text.regex
var string = /* some string */
when (RegexWhenArgument(string)) {
Regex( /* pattern */ ) -> /* do stuff */
Regex( /* pattern */ ) -> /* do stuff */
/* etc */
}
E la definizione minima della classe wrapper per l'argomento di espressione when
:
class RegexWhenArgument (val whenArgument: CharSequence) {
operator fun equals(whenEntry: Regex) = whenEntry.matches(whenArgument)
override operator fun equals(whenEntry: Any?) = (whenArgument == whenEntry)
}
Introduzione alle espressioni regolari in Kotlin
Questo post mostra come utilizzare la maggior parte delle funzioni nella classe Regex
, lavorare con null in modo sicuro correlato alle funzioni Regex
e come le stringhe raw rendano più facile scrivere e leggere i modelli regex.
La classe RegEx
Per lavorare con le espressioni regolari in Kotlin, devi usare la classe Regex(pattern: String)
e invocare funzioni come find(..)
o replace(..)
su quell'oggetto regex.
Un esempio su come utilizzare la classe Regex
che restituisce true se la stringa di input
contiene c o d:
val regex = Regex(pattern = "c|d")
val matched = regex.containsMatchIn(input = "abc") // matched: true
La cosa essenziale da capire con tutte le funzioni di Regex
è che il risultato è basato sulla corrispondenza tra il pattern
regex e la stringa di input
. Alcune funzioni richiedono una corrispondenza completa, mentre il resto richiede solo una corrispondenza parziale. La funzione containsMatchIn(..)
utilizzata nell'esempio richiede una corrispondenza parziale e viene illustrata più avanti in questo post.
Sicurezza nulla con espressioni regolari
Sia find(..)
che matchEntire(..)
restituiranno MatchResult?
oggetto. Il ?
carattere dopo MatchResult
è necessario affinchè Kotlin gestisca il null in modo sicuro .
Un esempio che dimostra come Kotlin gestisce nettamente in sicurezza da una funzione Regex
, quando la funzione find(..)
restituisce null:
val matchResult =
Regex("c|d").find("efg") // matchResult: null
val a = matchResult?.value // a: null
val b = matchResult?.value.orEmpty() // b: ""
a?.toUpperCase() // Still needs question mark. => null
b.toUpperCase() // Accesses the function directly. => ""
Con la funzione orEmpty()
, b
non può essere nullo e il ?
il carattere non è necessario quando si chiamano le funzioni su b
.
Se non ti interessa questa gestione sicura dei valori nulli, Kotlin ti permette di lavorare con valori null come in Java con !!
personaggi:
a!!.toUpperCase() // => KotlinNullPointerException
Stringhe raw nei pattern regex
Kotlin fornisce un miglioramento rispetto a Java con una stringa non elaborata che consente di scrivere schemi regex puri senza doppi backslash, necessari con una stringa Java. Una stringa grezza è rappresentata con una citazione tripla:
"""\d{3}-\d{3}-\d{4}""" // raw Kotlin string
"\\d{3}-\\d{3}-\\d{4}" // standard Java string
find (input: CharSequence, startIndex: Int): MatchResult?
La stringa di input
verrà confrontata con il pattern
nell'oggetto Regex
. Restituisce un Matchresult?
oggetto con il primo testo abbinato dopo startIndex
, o null
se il modello non corrisponde alla stringa di input
. La stringa del risultato viene recuperata da MatchResult?
proprietà del value
dell'oggetto. Il parametro startIndex
è facoltativo con il valore predefinito 0.
Per estrarre il primo numero di telefono valido da una stringa con i dettagli del contatto:
val phoneNumber :String? = Regex(pattern = """\d{3}-\d{3}-\d{4}""")
.find(input = "phone: 123-456-7890, e..")?.value // phoneNumber: 123-456-7890
Con nessun numero di telefono valido nella stringa di input
, la variabile phoneNumber
sarà null
.
findAll (input: CharSequence, startIndex: Int): Sequence
Restituisce tutte le corrispondenze dalla stringa di input
che corrisponde al pattern
regex.
Per stampare tutti i numeri separati con lo spazio, da un testo con lettere e cifre:
val matchedResults = Regex(pattern = """\d+""").findAll(input = "ab12cd34ef")
val result = StringBuilder()
for (matchedText in matchedResults) {
result.append(matchedText.value + " ")
}
println(result) // => 12 34
La variabile matchedResults
è una sequenza con oggetti MatchResult
. Con una stringa di input
senza cifre, la funzione findAll(..)
restituirà una sequenza vuota.
matchEntire (input: CharSequence): MatchResult?
Se tutti i caratteri nella stringa di input
corrispondono al pattern
regex, verrà restituita una stringa uguale input
. Altrimenti, verrà restituito null
.
Restituisce la stringa di input se l'intera stringa di input è un numero:
val a = Regex("""\d+""").matchEntire("100")?.value // a: 100
val b = Regex("""\d+""").matchEntire("100 dollars")?.value // b: null
matches (input: CharSequence): Boolean
Restituisce true se l'intera stringa di input corrisponde al modello regex. Falso altrimenti.
Verifica se due stringhe contengono solo cifre:
val regex = Regex(pattern = """\d+""")
regex.matches(input = "50") // => true
regex.matches(input = "50 dollars") // => false
containsMatchIn (input: CharSequence): Boolean
Restituisce true se parte della stringa di input corrisponde al modello regex. Falso altrimenti.
Verifica se due stringhe contengono almeno una cifra:
Regex("""\d+""").containsMatchIn("50 dollars") // => true
Regex("""\d+""").containsMatchIn("Fifty dollars") // => false
split (input: CharSequence, limit: Int): List
Restituisce una nuova lista senza tutte le corrispondenze regolari.
Per restituire liste senza cifre:
val a = Regex("""\d+""").split("ab12cd34ef") // a: [ab, cd, ef]
val b = Regex("""\d+""").split("This is a test") // b: [This is a test]
C'è un elemento nell'elenco per ogni divisione. La prima stringa di input
ha tre numeri. Ciò si traduce in una lista con tre elementi.
replace (input: CharSequence, replacement: String): String
Sostituisce tutte le corrispondenze del pattern
regex nella stringa di input
con la stringa di sostituzione.
Per sostituire tutte le cifre in una stringa con una x:
val result = Regex("""\d+""").replace("ab12cd34ef", "x") // result: abxcdxef