Selbst wenn die matchesInString()
Methode a String
als erstes Argument verwendet, funktioniert sie intern mit NSString
, und der Bereichsparameter muss unter Verwendung der NSString
Länge und nicht als Swift-Zeichenfolgenlänge angegeben werden. Andernfalls schlägt dies für "erweiterte Graphemcluster" wie "Flags" fehl.
Ab Swift 4 (Xcode 9) bietet die Swift-Standardbibliothek Funktionen zum Konvertieren zwischen Range<String.Index>
und 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 []
}
}
Beispiel:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Hinweis: Das erzwungene Entpacken Range($0.range, in: text)!
ist sicher, da sich das NSRange
auf einen Teilstring der angegebenen Zeichenfolge bezieht text
. Wenn Sie dies jedoch vermeiden möchten, verwenden Sie
return results.flatMap {
Range($0.range, in: text).map { String(text[$0]) }
}
stattdessen.
(Ältere Antwort für Swift 3 und früher :)
Sie sollten also die angegebene Swift-Zeichenfolge in eine konvertieren NSString
und dann die Bereiche extrahieren. Das Ergebnis wird automatisch in ein Swift-String-Array konvertiert.
(Der Code für Swift 1.2 befindet sich im Bearbeitungsverlauf.)
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 []
}
}
Beispiel:
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 []
}
}
Beispiel:
let string = "🇩🇪€4€9"
let matched = matches(for: "[0-9]", in: string)
print(matched)
// ["4", "9"]
Meine Antwort baut auf den gegebenen Antworten auf, macht aber den Regex-Abgleich durch Hinzufügen zusätzlicher Unterstützung robuster:
do/catch
nicht auf der Konsole gedruckt wird, und verwendet dasguard
KonstruktmatchingStrings
als Erweiterung hinzuString
Swift 4.2
Swift 3
Swift 2
quelle
try?
kann verwendet werden, wenn Sie nur am Ergebnis des Anrufs interessiert sind, nicht an einer möglichen Fehlermeldung. Also ja,guard try? ..
ist in Ordnung, aber wenn Sie den Fehler drucken möchten, benötigen Sie einen Do-Block. Beide Wege sind schnell.Wenn Sie Teilzeichenfolgen aus einem String extrahieren möchten, nicht nur die Position (sondern den tatsächlichen String einschließlich Emojis). Dann ist das Folgende vielleicht eine einfachere Lösung.
Anwendungsbeispiel:
Wird Folgendes zurückgeben:
Beachten Sie, dass die Verwendung von "\ w +" ein unerwartetes "" erzeugen kann.
Gibt dieses String-Array zurück
quelle
Ich habe festgestellt, dass die Lösung der akzeptierten Antwort unter Swift 3 für Linux leider nicht kompiliert werden kann. Hier ist also eine modifizierte Version, die Folgendes tut:
Die Hauptunterschiede sind:
Swift unter Linux scheint das Löschen des
NS
Präfixes für Foundation-Objekte zu erfordern, für die es kein Swift-natives Äquivalent gibt. (Siehe Swift Evolution-Vorschlag Nr. 86. )Für Swift unter Linux müssen außerdem die
options
Argumente sowohl für dieRegularExpression
Initialisierung als auch für diematches
Methode angegeben werden.Aus irgendeinem Grund funktioniert das Erzwingen von a
String
in a unterNSString
Swift unter Linux nicht, aber das Initialisieren eines neuenNSString
mit a,String
da die Quelle funktioniert.Diese Version funktioniert auch mit Swift 3 unter macOS / Xcode, mit der einzigen Ausnahme, dass Sie den Namen
NSRegularExpression
anstelle von verwenden müssenRegularExpression
.quelle
@ p4bloch Wenn Sie Ergebnisse aus einer Reihe von Erfassungsklammern erfassen möchten, müssen Sie stattdessen die
rangeAtIndex(index)
Methode vonNSTextCheckingResult
verwendenrange
. Hier ist die Methode von @MartinR für Swift2 von oben, angepasst für die Erfassung von Klammern. In dem zurückgegebenen Array ist das erste Ergebnis[0]
die gesamte Erfassung, und dann beginnen einzelne Erfassungsgruppen[1]
. Ich habe diemap
Operation auskommentiert (damit ich leichter sehen kann, was ich geändert habe) und sie durch verschachtelte Schleifen ersetzt.Ein Beispiel für einen Anwendungsfall könnte sein, dass Sie beispielsweise eine Zeichenfolge von
title year
"Finding Dory 2016" teilen möchten :quelle
[String?]
Imfor i in 0..<result.numberOfRanges
Block müssen Sie einen Test hinzufügen, der die Übereinstimmung nur anfügt, wenn der Bereich! = Ist.NSNotFound
Andernfalls sollte er null anhängen. Siehe: stackoverflow.com/a/31892241/2805570Swift 4 ohne NSString.
quelle
NSMakeRange(0, self.count)
ist nicht korrekt, daself
es sich um einString
(= UTF8) und keinNSString
(= UTF16) handelt. Dasself.count
ist also nicht unbedingt dasselbe wiensString.length
(wie in anderen Lösungen verwendet). Sie können die Bereichsberechnung durchNSRange(self.startIndex..., in: self)
Die meisten der oben genannten Lösungen ergeben nur die vollständige Übereinstimmung, da die Erfassungsgruppen ignoriert werden, z. B.: ^ \ D + \ s + (\ d +)
Um die erwarteten Erfassungsgruppenübereinstimmungen zu erhalten, benötigen Sie Folgendes wie (Swift4):
quelle
for index in 0..<matches.count {
umlet 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)) } }
So habe ich es gemacht, ich hoffe, es bringt eine neue Perspektive, wie das bei Swift funktioniert.
In diesem Beispiel unten erhalte ich eine beliebige Zeichenfolge zwischen
[]
quelle
Dies ist eine sehr einfache Lösung, die ein Array von Zeichenfolgen mit den Übereinstimmungen zurückgibt
Swift 3.
quelle
Der schnellste Weg, um alle Übereinstimmungen zurückzugeben und Gruppen in Swift 5 zu erfassen
Gibt ein zweidimensionales Array von Zeichenfolgen zurück:
kehrt zurück...
quelle
Ein großes Dankeschön an Lars Blumberg für seine Antwort auf die Erfassung von Gruppen und vollständigen Spielen mit Swift 4 , was mir sehr geholfen hat. Ich habe es auch für die Personen hinzugefügt, die eine error.localizedDescription-Antwort wünschen, wenn ihre Regex ungültig ist:
Für mich hat es geholfen, die localizedDescription als Fehler zu verstehen, was beim Escape schief gelaufen ist, da sie anzeigt, welche endgültige Regex-Methode Swift zu implementieren versucht.
quelle