Incluso si el matchesInString()
método toma a String
como primer argumento, funciona internamente NSString
y el parámetro de rango debe proporcionarse utilizandoNSString
longitud y no como la longitud de la cadena Swift. De lo contrario, fallará para "grupos de grafemas extendidos" como "banderas".
A partir de Swift 4 (Xcode 9), la biblioteca estándar de Swift proporciona funciones para convertir entre Range<String.Index>
y NSRange
.
func matches(for regex: String, in text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex)
let results = regex.matches(in: text,
range: NSRange(text.startIndex..., in: text))
return results.map {
String(text[Range($0.range, in: text)!])
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
Ejemplo:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Nota: El desenvolvimiento forzado Range($0.range, in: text)!
es seguro porque se NSRange
refiere a una subcadena de la cadena dada text
. Sin embargo, si desea evitarlo, use
return results.flatMap {
Range($0.range, in: text).map { String(text[$0]) }
}
en lugar.
(Respuesta anterior para Swift 3 y anteriores :)
Por lo tanto, debe convertir la cadena Swift dada en un NSString
y luego extraer los rangos. El resultado se convertirá en una matriz de cadenas Swift automáticamente.
(El código para Swift 1.2 se puede encontrar en el historial de edición).
Swift 2 (Xcode 7.3.1):
func matchesForRegexInText(regex: String, text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex, options: [])
let nsString = text as NSString
let results = regex.matchesInString(text,
options: [], range: NSMakeRange(0, nsString.length))
return results.map { nsString.substringWithRange($0.range)}
} catch let error as NSError {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
Ejemplo:
let string = "🇩🇪€4€9"
let matches = matchesForRegexInText("[0-9]", text: string)
print(matches)
// ["4", "9"]
Swift 3 (Xcode 8)
func matches(for regex: String, in text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex)
let nsString = text as NSString
let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
return results.map { nsString.substring(with: $0.range)}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
Ejemplo:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Mi respuesta se basa en las respuestas dadas, pero hace que la coincidencia de expresiones regulares sea más sólida al agregar soporte adicional:
do/catch
no imprimir en la consola y hace uso de laguard
construcciónmatchingStrings
como una extensión aString
Swift 4.2
Swift 3
Swift 2
fuente
try?
puede usarse si solo está interesado en el resultado de la llamada, no en un posible mensaje de error. Entonces sí,guard try? ..
está bien, pero si desea imprimir el error, entonces necesita un do-block. Ambas formas son rápidas.Si desea extraer subcadenas de una Cadena, no solo la posición (sino la Cadena real, incluidos los emojis). Entonces, lo siguiente quizás sea una solución más simple.
Ejemplo de uso:
Devolverá lo siguiente:
Nota usando "\ w +" puede producir un inesperado ""
Devolverá esta matriz de cadenas
fuente
Descubrí que la solución de la respuesta aceptada desafortunadamente no se compila en Swift 3 para Linux. Aquí hay una versión modificada, entonces, que sí:
Las principales diferencias son:
Swift en Linux parece requerir que se suelte el
NS
prefijo en los objetos Foundation para los que no existe un equivalente nativo de Swift. (Ver la propuesta de evolución rápida # 86. )Swift en Linux también requiere especificar los
options
argumentos para laRegularExpression
inicialización y elmatches
método.Por alguna razón, coaccionar un
String
en unNSString
no funciona en Swift en Linux sino inicializar un nuevoNSString
con unString
como la fuente sí funciona.Esta versión también funciona con Swift 3 en macOS / Xcode con la única excepción de que debe usar el nombre en
NSRegularExpression
lugar deRegularExpression
.fuente
@ p4bloch si desea capturar resultados de una serie de paréntesis de captura, debe utilizar el
rangeAtIndex(index)
método deNSTextCheckingResult
, en lugar derange
. Aquí está el método de @MartinR para Swift2 desde arriba, adaptado para paréntesis de captura. En la matriz que se devuelve, el primer resultado[0]
es la captura completa, y luego comienzan los grupos de captura individuales[1]
. Comenté lamap
operación (por lo que es más fácil ver lo que cambié) y la reemplacé por bucles anidados.Un ejemplo de uso podría ser, digamos que desea dividir una cadena de,
title year
por ejemplo, "Finding Dory 2016", podría hacer esto:fuente
[String?]
y en elfor i in 0..<result.numberOfRanges
bloque, debe agregar una prueba que solo agrega la coincidencia si el rango! =NSNotFound
, De lo contrario, debería agregar nil. Ver: stackoverflow.com/a/31892241/2805570Swift 4 sin NSString.
fuente
NSMakeRange(0, self.count)
no es correcta, porqueself
es unString
(= UTF8) y no unNSString
(= UTF16). Entonces,self.count
no es necesariamente lo mismo quensString.length
(como se usa en otras soluciones). Puede reemplazar el cálculo del rango conNSRange(self.startIndex..., in: self)
La mayoría de las soluciones anteriores solo dan la coincidencia completa como resultado ignorando los grupos de captura, por ejemplo: ^ \ d + \ s + (\ d +)
Para obtener las coincidencias del grupo de captura como se esperaba, necesita algo como (Swift4):
fuente
for index in 0..<matches.count {
alrededorlet lastRange... results.append(matchedString)}
for i in 1...lastRangeIndex { let capturedGroupIndex = match.range(at: i) if capturedGroupIndex.location != NSNotFound { let matchedString = (self as NSString).substring(with: capturedGroupIndex) results.append(matchedString.trimmingCharacters(in: .whitespaces)) } }
Así es como lo hice, espero que traiga una nueva perspectiva de cómo funciona esto en Swift.
En este ejemplo a continuación, obtendré cualquier cadena entre
[]
fuente
Esta es una solución muy simple que devuelve una matriz de cadenas con las coincidencias.
Swift 3.
fuente
La forma más rápida de devolver todos los partidos y capturar grupos en Swift 5
Devuelve una matriz de cadenas de 2 dimensiones:
devoluciones...
fuente
Muchas gracias a Lars Blumberg por su respuesta por capturar grupos y partidos completos con Swift 4 , lo que me ayudó mucho. También hice una adición para las personas que quieren una respuesta error.localizedDescription cuando su expresión regular no es válida:
Para mí, tener la Descripción localizada como error me ayudó a comprender qué salió mal al escapar, ya que muestra qué final regex swift intenta implementar.
fuente