Mesmo que o matchesInString()
método String
seja o primeiro argumento, ele trabalha internamente com NSString
, e o parâmetro range deve ser fornecido usando o parâmetroNSString
comprimento e não o comprimento da string Swift. Caso contrário, falhará em "grupos de grafemas estendidos", como "sinalizadores".
A partir do Swift 4 (Xcode 9), a biblioteca padrão do Swift fornece funções para converter entre Range<String.Index>
e 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 []
}
}
Exemplo:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Nota: O desembrulhamento forçado Range($0.range, in: text)!
é seguro porque NSRange
refere-se a uma substring da sequência especificada text
. No entanto, se você quiser evitá-lo, use
return results.flatMap {
Range($0.range, in: text).map { String(text[$0]) }
}
em vez de.
(Resposta mais antiga para Swift 3 e versões anteriores :)
Portanto, você deve converter a sequência Swift fornecida em um NSString
e extrair os intervalos. O resultado será convertido para uma matriz de sequências Swift automaticamente.
(O código do Swift 1.2 pode ser encontrado no histórico de edições.)
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 []
}
}
Exemplo:
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 []
}
}
Exemplo:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Minha resposta se baseia em respostas dadas, mas torna a correspondência de expressões regulares mais robusta adicionando suporte adicional:
do/catch
não imprimir no console e faz uso daguard
construçãomatchingStrings
como uma extensão aoString
Swift 4.2
Swift 3
Swift 2
fonte
try?
pode ser usado se você estiver interessado apenas no resultado da chamada, e não em uma possível mensagem de erro. Então, sim, tudoguard try? ..
bem, mas se você quiser imprimir o erro, precisará de um bloco de tarefas. Ambas as formas são Swifty.Se você deseja extrair substrings de uma String, não apenas a posição (mas a String real, incluindo emojis). Em seguida, talvez seja uma solução mais simples.
Exemplo de uso:
Retornará o seguinte:
Nota usando "\ w +" pode produzir um "" inesperado
Retornará essa matriz String
fonte
Descobri que a solução da resposta aceita infelizmente não é compilada no Swift 3 para Linux. Aqui está uma versão modificada, então, que faz:
As principais diferenças são:
O Swift no Linux parece exigir a exclusão do
NS
prefixo nos objetos Foundation para os quais não há equivalente nativo do Swift. (Veja a proposta de evolução Swift nº 86 ).O Swift no Linux também requer a especificação dos
options
argumentos para aRegularExpression
inicialização e omatches
método.Por alguma razão, coagir um
String
para umNSString
não funciona no Swift no Linux, mas inicializar um novoNSString
com um àString
medida que a fonte funciona.Esta versão também funciona com o Swift 3 no macOS / Xcode, com a única exceção de que você deve usar o nome em
NSRegularExpression
vez deRegularExpression
.fonte
@ p4bloch se você deseja capturar resultados de uma série de parênteses de captura, precisa usar o
rangeAtIndex(index)
método deNSTextCheckingResult
, em vez derange
. Aqui está o método do @MartinR para o Swift2 de cima, adaptado para os parênteses de captura. Na matriz retornada, o primeiro resultado[0]
é a captura inteira e, em seguida, começam grupos de captura individuais[1]
. Comentei amap
operação (para que seja mais fácil ver o que eu mudei) e a substitui por loops aninhados.Um exemplo de caso de uso pode ser, digamos que você queira dividir uma sequência de
title year
por exemplo, "Procurando o Dory 2016", você pode fazer isso:fonte
[String?]
e, nofor i in 0..<result.numberOfRanges
bloco, é necessário adicionar um teste que apenas acrescenta a correspondência se o intervalo! =NSNotFound
, Caso contrário, deve acrescentar nulo. Veja: stackoverflow.com/a/31892241/2805570Swift 4 sem NSString.
fonte
NSMakeRange(0, self.count)
não está correto, porqueself
é umString
(= UTF8) e não umNSString
(= UTF16). Portanto,self.count
não é necessariamente o mesmo quensString.length
(usado em outras soluções). Você pode substituir o cálculo do intervalo porNSRange(self.startIndex..., in: self)
A maioria das soluções acima fornece apenas a correspondência completa como resultado, ignorando os grupos de captura, por exemplo: ^ \ d + \ s + (\ d +)
Para obter as correspondências do grupo de captura conforme o esperado, você precisa de algo como (Swift4):
fonte
for index in 0..<matches.count {
em tornolet 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)) } }
Foi assim que eu fiz, espero que traga uma nova perspectiva de como isso funciona no Swift.
Neste exemplo abaixo, receberei a string any entre
[]
fonte
Esta é uma solução muito simples que retorna uma matriz de string com as correspondências
Swift 3.
fonte
A maneira mais rápida de retornar todas as partidas e capturar grupos no Swift 5
Retorna uma matriz bidimensional de seqüências de caracteres:
retorna ...
fonte
Muito obrigado a Lars Blumberg, sua resposta pela captura de grupos e partidas completas com o Swift 4 , o que me ajudou muito. Também fiz um acréscimo para as pessoas que desejam uma resposta error.localizedDescription quando o regex deles é inválido:
O fato de eu ter a descrição localizada como erro ajudou a entender o que deu errado com a fuga, uma vez que é exibida qual regex final rápido tenta implementar.
fonte