Nawet jeśli matchesInString()
metoda przyjmuje a String
jako pierwszy argument, działa wewnętrznie z NSString
, a parametr range musi być podawany przy użyciu NSString
długości, a nie jako długości łańcucha Swift. W przeciwnym razie zakończy się niepowodzeniem dla „rozszerzonych klastrów grafemów”, takich jak „flagi”.
Począwszy od Swift 4 (Xcode 9), standardowa biblioteka Swift zapewnia funkcje do konwersji między Range<String.Index>
i 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 []
}
}
Przykład:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Uwaga: wymuszone rozpakowanie Range($0.range, in: text)!
jest bezpieczne, ponieważ NSRange
odwołuje się do podłańcucha danego ciągu text
. Jeśli jednak chcesz tego uniknąć, użyj
return results.flatMap {
Range($0.range, in: text).map { String(text[$0]) }
}
zamiast.
(Starsza odpowiedź dla Swift 3 i wcześniejszych :)
Dlatego powinieneś przekonwertować podany ciąg Swift na ciąg, NSString
a następnie wyodrębnić zakresy. Wynik zostanie automatycznie przekonwertowany na tablicę ciągów Swift.
(Kod dla Swift 1.2 można znaleźć w historii edycji).
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 []
}
}
Przykład:
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 []
}
}
Przykład:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Moja odpowiedź opiera się na udzielonych odpowiedziach, ale sprawia, że dopasowywanie wyrażeń regularnych jest bardziej niezawodne, dodając dodatkowe wsparcie:
do/catch
, nie drukując na konsoli i używaguard
konstrukcjimatchingStrings
jako rozszerzenie doString
Swift 4.2
Szybki 3
Szybki 2
źródło
try?
można użyć, jeśli interesuje Cię tylko wynik połączenia, a nie ewentualny komunikat o błędzie. Więc tak,guard try? ..
jest w porządku, ale jeśli chcesz wydrukować błąd, potrzebujesz bloku do. Oba sposoby są szybkie.Jeśli chcesz wyodrębnić podciągi z ciągu znaków, a nie tylko pozycję (ale rzeczywisty ciąg zawierający emotikony). Następujące może być prostszym rozwiązaniem.
Przykładowe zastosowanie:
Zwróci następujące informacje:
Uwaga po użyciu „\ w +” może spowodować nieoczekiwany „”
Zwróci tę tablicę String
źródło
Okazało się, że rozwiązanie zaakceptowanej odpowiedzi niestety nie kompiluje się na Swift 3 dla systemu Linux. Oto zmodyfikowana wersja, która robi:
Główne różnice to:
Wydaje się, że język Swift w systemie Linux wymaga usunięcia
NS
prefiksu w obiektach Foundation, dla których nie ma odpowiednika w języku Swift. (Zobacz propozycję szybkiej ewolucji nr 86 ).Swift w systemie Linux wymaga również określenia
options
argumentów zarówno dlaRegularExpression
inicjalizacji, jak imatches
metody.Z jakiegoś powodu wymuszenie a
String
na anNSString
nie działa w Swift w systemie Linux, ale inicjowanie nowego zaNSString
pomocą aString
jako źródła działa.Ta wersja działa również ze Swift 3 w systemie macOS / Xcode z jedynym wyjątkiem, że musisz użyć nazwy
NSRegularExpression
zamiastRegularExpression
.źródło
@ p4bloch jeśli chcesz przechwycić wyniki z serii przechwytywania nawiasów, musisz użyć
rangeAtIndex(index)
metodyNSTextCheckingResult
zamiastrange
. Oto metoda @MartinR dla Swift2 z góry, dostosowana do przechwytywania nawiasów. W zwracanej tablicy pierwszym wynikiem[0]
jest całe przechwytywanie, a następnie poszczególne grupy przechwytywania rozpoczynają się od[1]
. Skomentowałemmap
operację (aby łatwiej było zobaczyć, co zmieniłem) i zastąpiłem ją zagnieżdżonymi pętlami.Przykładowym przypadkiem użycia może być, powiedzmy, że chcesz podzielić ciąg
title year
np. „Finding Dory 2016”, możesz to zrobić:źródło
[String?]
iwfor i in 0..<result.numberOfRanges
bloku trzeba dodać test, który dopisuje dopasowanie tylko wtedy, gdy zakres! =NSNotFound
, W przeciwnym razie powinien dopisać nil. Zobacz: stackoverflow.com/a/31892241/2805570Swift 4 bez NSString.
źródło
NSMakeRange(0, self.count)
nie jest poprawne, ponieważself
jestString
(= UTF8), a nieNSString
(= UTF16). Więcself.count
niekoniecznie jest to to samo, consString.length
(używane w innych rozwiązaniach). Obliczenie zakresu można zamienić naNSRange(self.startIndex..., in: self)
Większość powyższych rozwiązań daje tylko pełne dopasowanie, ignorując grupy przechwytywania, np .: ^ \ d + \ s + (\ d +)
Aby dopasować grupy przechwytywania zgodnie z oczekiwaniami, potrzebujesz czegoś takiego jak (Swift4):
źródło
for index in 0..<matches.count {
dookołalet 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)) } }
Tak to zrobiłem, mam nadzieję, że to przyniesie nową perspektywę, jak to działa w Swift.
W tym przykładzie poniżej otrzymam dowolny ciąg między
[]
źródło
To bardzo proste rozwiązanie, które zwraca tablicę łańcuchów z dopasowaniami
Szybki 3.
źródło
Najszybszy sposób na zwrócenie wszystkich meczów i grup przechwytywania w Swift 5
Zwraca dwuwymiarową tablicę ciągów:
zwroty...
źródło
Wielkie dzięki dla Larsa Blumberga za jego odpowiedź za przechwytywanie grup i pełnych meczy za pomocą Swift 4 , co bardzo mi pomogło. Dodałem również do tego dla osób, które chcą otrzymać odpowiedź error.localizedDescription, gdy ich wyrażenie regularne jest nieprawidłowe:
Dla mnie posiadanie localizedDescription jako błędu pomogło zrozumieć, co poszło nie tak z ucieczką, ponieważ wyświetla on, który ostateczny regex swift próbuje zaimplementować.
źródło