web-dev-qa-db-de.com

Swift Liefert einen String zwischen zwei Strings in einem String

Ich bekomme eine Zeichenfolge von HTML-Parse, die ist;

string = "javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"

mein Code ist so etwas

var startIndex = text.rangeOfString("'")
var endIndex = text.rangeOfString("',")
var range2 = startIndex2...endIndex
substr= string.substringWithRange(range)

ich bin mir nicht sicher, ob meine zweite Zeichenfolge "'" oder "',"

ich möchte mein Ergebnis als 

substr = "Info/99/something"
25
alp

Ich würde einen regulären Ausdruck verwenden, um Teilstrings aus komplexen Eingaben wie diesem zu extrahieren.

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
18
seb

Swift 4

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])
            }
        }
    }
}

Swift 3

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
                substring(with: substringFrom..<substringTo)
            }
        }
    }
}

Alte Antwort:

import Foundation

extension String {
  func sliceFrom(start: String, to: String) -> String? {
    return (rangeOfString(start)?.endIndex).flatMap { sInd in
      (rangeOfString(to, range: sInd..<endIndex)?.startIndex).map { eInd in
        substringWithRange(sInd..<eInd)
      }
    }
  }
}

"javascript:getInfo(1,'Info/99/something', 'City Hall',1, 99);"
  .sliceFrom("'", to: "',")
73
oisdk

Dies funktioniert, wenn es immer der zweite Split ist:

let subString = split(string, isSeparator: "'")[1]
5
Qbyte

Sie können var arr = str.componentsSeparatedByString(",") als zweiten Split verwenden, der Ihr Array zurückgibt

5
iAnurag

Erwägen Sie die Verwendung eines regulären Ausdrucks, um alles zwischen einfachen Anführungszeichen zu finden.

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])
3
litso

Swift 4.2:

extension String {

    //right is the first encountered string after left
    func between(_ left: String, _ right: String) -> String? {
        guard let leftRange = range(of: left), let rightRange = range(of: right, options: .backwards)
            ,leftRange.upperBound <= rightRange.lowerBound else { return nil }

        let sub = self[leftRange.upperBound...]
        let closestToLeftRange = sub.range(of: right)!
        return String(sub[..<closestToLeftRange.lowerBound])
    }

}
2
Devansh Vyas

Ich habe eine der Top Swift 4 Antworten umgeschrieben, um zu verstehen, dass dies mit map geschah. Ich bevorzuge eine Version mit guard, IMO

Es wäre einfach, Optionen für die Rückwärtssuche usw. hinzuzufügen.

extension String {

    func slice(from: String, to: String) -> String? {
        guard let rangeFrom = range(of: from)?.upperBound else { return nil }
        guard let rangeTo = self[rangeFrom...].range(of: to)?.lowerBound else { return nil }
        return String(self[rangeFrom..<rangeTo])
    }

}

let test1 = "a[b]c".slice(from: "[", to: "]")   // "b"
let test2 = "abc".slice(from: "[", to: "]")     // nil
let test3 = "a]b[c".slice(from: "[", to: "]")   // nil
let test4 = "[a[b]c]".slice(from: "[", to: "]") // "a[b"
0
pkamb

In Swift 4 oder höher können Sie eine Erweiterungsmethode für StringProtocol erstellen, um auch Teilzeichenfolgen zu unterstützen. Sie können einfach eine Substring anstelle eines neuen Strings zurückgeben:

extension StringProtocol where Index == String.Index {
    func substring(from start: String, to end: String? = nil, options: String.CompareOptions = []) -> SubSequence? {
        guard let lower = range(of: start, options: options)?.upperBound else { return nil }
        guard let end = end else { return self[lower...] }
        guard let upper = self[lower...].range(of: end, options: options)?.lowerBound else { return nil }
        return self[lower..<upper]
    }
}

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 subString = string.subString(from: "'", to: "',")  // "Info/99/something"

let subStringCaseInsensitive = string.subString(from: "'info/", to: "/something", options: .caseInsensitive)  // "99"
0
Leo Dabus

Swift 4-Version von @litso. Um alle Werte im Text zu finden

    func find(inText text: String, pattern: String) -> [String]? {
        do {
            let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
            let result = regex.matches(in: text, options: .init(rawValue: 0), range: NSRange(location: 0, length: text.count))

            let matches = result.map { result in
                return (text as NSString).substring(with: result.range)
            }

            return matches
        } catch {
            print(error)
        }
        return nil
    }
0
Arek