在Swift中使用正则表达式定位双引号

4
我一直在尝试使用Swift中的正则表达式从字符串中提取文本。我想要提取的文本位于双引号内,因此我正在尝试定位那些双引号并获取其中的文本。这是我正在使用的正则表达式:(?<=")(?:\\.|[^"\\])*(?="),它可以很好地处理任何类型的文本,甚至可以更简单,因为我正在寻找那些可能在双引号内的任何东西。
当我尝试在Swift中使用这个正则表达式时,我必须转义其中的双引号,但由于某种原因,正则表达式不能使用转义后的双引号,例如(?<=\")(?:\\.|[^\"\\])*(?=\")。即使我尝试使用像\"这样简单的内容,正则表达式也无法匹配字符串中的任何一个双引号。
代码示例:
func extractText(sentence: String?) -> String {
    let pattern = "(?<=\")(?:\\.|[^\"\\])*(?=\")"
    let source = sentence!

    if let range = source.range(of: pattern, options: .regularExpression) {
        return "Text: \(source[range])"
    }

    return ""
}

extractText("Hello \"this is\" a test") -> "this is"

需要注意:

  • 所有这些正则表达式都必须放在双引号中,以创建将用作模式的字符串文字。
  • 我正在使用String的range方法和.regularExpression选项来匹配内容。
  • 我正在使用Swift 4和Xcode 9 Playground

如何在Swift中转义双引号以成功匹配字符串中的双引号?

解决方案

感谢@Atlas_Gondal和@vadian的帮助,我注意到问题“部分”不是RegExp,而是我得到的字符串使用不同类型的双引号“ ... ”,所以我必须更改我的模式为"(?<=“).*(?=”)"才能使用它。

结果代码如下:

func extractText(sentence: String?) -> String {
    let pattern = "(?<=“).*(?=”)"
    let source = sentence!

    if let range = source.range(of: pattern, options: .regularExpression) {
        return "\(source[range])"
    }

    return ""
}

在引号开头之前有可能出现一个转义字符,(?<!\\") 可以防止匹配。因此,总的来说,现在应该是 (?<!\\")(?<=") - user557597
顺便提一下,所有正则表达式引擎都将 (?<=\") 解释为 (?<="),所以如果它现在无法工作,那么可能是语言解析字符串时出了问题。 - user557597
目前,此代码仅提取整个字符串中用单引号括起来的单词。如果该字符串中有多个带引号的单词,则无法正常工作。需要帮助吗? - nr5
3个回答

4

range(ofregularExpression选项无法捕获组,因此无法实现该功能。

您需要使用真正的NSRegularExpression

func extractText(sentence: String) -> String {
    let pattern = "\"([^\"]+)\""
    let regex = try! NSRegularExpression(pattern: pattern)


    if let match = regex.firstMatch(in: sentence, range: NSRange(sentence.startIndex..., in: sentence)) {
        let range = Range(match.range(at: 1), in: sentence)!
        return String(sentence[range])
    }

    return ""
}

extractText(sentence:"Hello \"this is\" a test")

该模式非常简单:搜索双引号,后跟一个或多个非双引号字符,然后是一个闭合双引号。捕获双引号之间的字符。
请注意,在文字串中的转义双引号只是虚拟转义。
PS: 在Swift 3和4中,您的代码如果没有参数标签将无法编译。

目前,此代码仅提取字符串中的单引号词。如果字符串中有多个带引号的词,则无法正常工作。需要帮助吗? - nr5
与其使用firstMatch,不如使用matches并使用循环迭代数组。 - vadian
你能否请检查这个链接:https://stackoverflow.com/questions/57852915/find-multiple-quoted-words-in-a-string-with-regex - nr5

0

虽然有点晚了,但我通过使用原始字符串来修复了它。

自从Swift 5以来,您可以这样做:

let pattern = #"(?<=“).*(?=”)"# // <- Note the # in front and after.
// ...

然后你就可以开始了。在我看来,这是迄今为止最简单的解决方案!

⚠️ 注意:这意味着双引号内的每个字符都被视为字面量(不再有模板("\(variable)")或换行符\n)。

这里有一篇关于原始字符串的好文章


0

尝试这段代码:

extension String {
func capturedGroups(withRegex pattern: String) -> [String] {
    var results = [String]()

    var regex: NSRegularExpression
    do {
        regex = try NSRegularExpression(pattern: pattern, options: [])
    } catch {
        return results
    }

    let matches = regex.matches(in: self, options: [], range: NSRange(location:0, length: self.characters.count))

    guard let match = matches.first else { return results }

    let lastRangeIndex = match.numberOfRanges - 1
    guard lastRangeIndex >= 1 else { return results }

    for i in 1...lastRangeIndex {
        let capturedGroupIndex = match.rangeAt(i)
        let matchedString = (self as NSString).substring(with: capturedGroupIndex)
        results.append(matchedString)
    }

    return results
}
}

使用扩展如下:
print("This is \"My String \"".capturedGroups(withRegex: "\"(.*)\""))

示例截图 在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接