Swift Get string between 2 strings in a string
Solution 1
I'd use a regular expression to extract substrings from complex input like this.
Swift 3.1:
let test = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
if let match = test.range(of: "(?<=')[^']+", options: .regularExpression) {
print(test.substring(with: match))
}
// Prints: Info/99/something
Swift 2.0:
let test = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
if let match = test.rangeOfString("(?<=')[^']+", options: .RegularExpressionSearch) {
print(test.substringWithRange(match))
}
// Prints: Info/99/something
Solution 2
extension String {
func slice(from: String, to: String) -> String? {
return (range(of: from)?.upperBound).flatMap { substringFrom in
(range(of: to, range: substringFrom..<endIndex)?.lowerBound).map { substringTo in
String(self[substringFrom..<substringTo])
}
}
}
}
"javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
.sliceFrom("'", to: "',")
Solution 3
In Swift 4 or later you can create an extension method on StringProtocol to support substrings as well. You can just return a Substring
instead of a new String:
edit/update: Swift 5 or later
extension StringProtocol {
func substring<S: StringProtocol>(from start: S, options: String.CompareOptions = []) -> SubSequence? {
guard let lower = range(of: start, options: options)?.upperBound
else { return nil }
return self[lower...]
}
func substring<S: StringProtocol>(through end: S, options: String.CompareOptions = []) -> SubSequence? {
guard let upper = range(of: end, options: options)?.upperBound
else { return nil }
return self[..<upper]
}
func substring<S: StringProtocol>(upTo end: S, options: String.CompareOptions = []) -> SubSequence? {
guard let upper = range(of: end, options: options)?.lowerBound
else { return nil }
return self[..<upper]
}
func substring<S: StringProtocol, T: StringProtocol>(from start: S, upTo end: T, options: String.CompareOptions = []) -> SubSequence? {
guard let lower = range(of: start, options: options)?.upperBound,
let upper = self[lower...].range(of: end, options: options)?.lowerBound
else { return nil }
return self[lower..<upper]
}
func substring<S: StringProtocol, T: StringProtocol>(from start: S, through end: T, options: String.CompareOptions = []) -> SubSequence? {
guard let lower = range(of: start, options: options)?.upperBound,
let upper = self[lower...].range(of: end, options: options)?.upperBound
else { return nil }
return self[lower..<upper]
}
}
Usage:
let string = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
let substr = string.substring(from: "'") // "Info/99/something', 'City Hall',1, 99);"
let through = string.substring(through: "Info") // "javascript:getInfo"
let upTo = string.substring(upTo: "Info") // "javascript:get"
let fromUpTo = string.substring(from: "'", upTo: "',") // "Info/99/something"
let fromThrough = string.substring(from: "'", through: "',") // "Info/99/something',"
let fromUpToCaseInsensitive = string.substring(from: "'info/", upTo: "/something", options: .caseInsensitive) // "99"
Solution 4
Consider using a regular expression to match everything between single quotes.
let string = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
let pattern = "'(.+?)'"
let regex = NSRegularExpression(pattern: pattern, options: nil, error: nil)
let results = regex!.matchesInString(string, options: nil, range: NSMakeRange(0, count(string))) as! [NSTextCheckingResult]
let nsstring = string as NSString
let matches = results.map { result in return nsstring.substringWithRange(result.range)}
// First match
println(matches[0])
![Alp](https://i.stack.imgur.com/iqSwc.jpg?s=256&g=1)
Alp
I am an enthusiastic game developer and game designer. I mostly work on unity3d engine and a little bit on unreal engine. I like dragons,wolves,horses. I have many hobbies; anime ,reading, running. fighting, wing tsun ,kickbox , ninjutsu, story writing and video games.
Updated on July 09, 2022Comments
-
Alp almost 2 years
I am getting a string from html parse that is;
string = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
my code is something like
var startIndex = text.rangeOfString("'") var endIndex = text.rangeOfString("',") var range2 = startIndex2...endIndex substr= string.substringWithRange(range)
i am not sure if my second splitting string should be "'" or "',"
i want my outcome as
substr = "Info/99/something"
-
CodyMace over 7 yearsThis is awesome! Thanks!
-
Makaille over 7 years@oisdk does it work if we need to slice from a string to the end of the string ? Ex : "blabla popo titi toto" -> slice(from "popo", to : endOfString) ?
-
Chameleon about 6 yearsamazing and simple
-
Martin R about 6 yearsIn Swift 4 you can also compute the second range as
self[substringFrom...].range(of: to)
, that saves some keystrokes and the mention ofendIndex
. -
pkamb over 4 yearsI found this
return flatmap.().map()
code pretty hard to grok for the function; so I tried rewriting a version usingguard
. -
bshirley over 4 yearsFor more detail on the regex, see stackoverflow.com/questions/6109882/…
-
Mendy almost 3 years@Makaille see this answer