swift中的正则表达式

Posted

技术标签:

【中文标题】swift中的正则表达式【英文标题】:Regular expressions in swift 【发布时间】:2019-05-18 02:49:45 【问题描述】:

我对 Swift 中的 NSRegularExpression 有点困惑,有人可以帮帮我吗?

task:1 给定("name","john","name of john") 那么我应该得到["name","john","name of john"]。在这里我应该避免使用括号。

task:2 给定("name"," john","name of john") 那么我应该得到["name","john","name of john"]。在这里我应该避免括号和额外的空格,最后得到字符串数组。

task:3 给定key = value // comment 那么我应该得到["key","value","comment"]。在这里,我应该通过避免 =// 只获得字符串中的字符串 我已经尝试了任务 1 的以下代码,但没有通过。

let string = "(name,john,string for user name)"
let pattern = "(?:\\w.*)"

do 
    let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
    let matches = regex.matches(in: string, options: [], range: NSRange(location: 0, length: string.utf16.count))
    for match in matches 
        if let range = Range(match.range, in: string) 
            let name = string[range]
            print(name)
        
    
 catch 
    print("Regex was bad!")

提前致谢。

【问题讨论】:

您发布的代码中的string 值与您问题中的任何“给定”任务都不匹配。一个有引号,另一个没有。 另请注意,任务 3 应该是与前两个任务分开的问题。 这是一个公正的用户输入,可能会或可能不会给出。例如没有引号。感谢@rmaddy 的回复。 您的任务 1 使用 ("name","john","name of john"),但您的代码 sn-p 使用的是 (name,john,string for user name)。它是哪一个?在子字符串周围加引号还是不加引号? 另外,您已经给出了子字符串本身不包含引号或逗号的示例。但是如果他们这样做了(例如,在子字符串中有一些转义字符)。如果你需要处理这个问题,你就开始进入一个正则表达式可能根本不是最佳方法的领域。 【参考方案1】:

用非字母数字字符分隔字符串,空格除外。然后用空格修剪元素。

extension String 
    func words() -> [String] 
        return self.components(separatedBy: CharacterSet.alphanumerics.inverted.subtracting(.whitespaces))
                .filter( !$0.isEmpty )
                .map( $0.trimmingCharacters(in: .whitespaces) )
    


let string1 = "(name,john,string for user name)"
let string2 = "(name,       john,name of john)"
let string3 = "key = value // comment"

print(string1.words())//["name", "john", "string for user name"]
print(string2.words())//["name", "john", "name of john"]
print(string3.words())//["key", "value", "comment"]

【讨论】:

谢谢@Rajeshkumar。你能帮我理解雷克斯吗?当我正在测试 VSCode 前工作但不是在 swift 中时。 请记住,对于字符串 3 中许多可能的值,此解决方案将失败。对于任何带有连字符、撇号或其他标点符号的名称,它都可能失败。【参考方案2】:

Swift 中的正则表达式

这些帖子可能会帮助您快速探索正则表达式:

Does a string match a pattern? Swift extract regex matches How can I use String slicing subscripts in Swift 4? How to use regex with Swift? Swift 3 - How do I extract captured groups in regular expressions? How to group search regular expressions using swift?

任务 1 和 2

此表达式可能会帮助您匹配任务 1 和 2 的所需输出:

"(\s+)?([a-z\s]+?)(\s+)?"


根据Rob 的建议,您可以大大减少边界,例如字符列表[a-z\s]。例如,在这里,我们也可以使用:

"(\s+)?(.*?)(\s+)?"

"(\s+)?(.+?)(\s+)?"

简单地传递两个 " 和/或 space 之间的所有内容。

正则表达式

如果这不是您想要的表达方式,您可以在regex101.com 中修改/更改您的表达方式。

正则表达式电路

你也可以在jex.im中可视化你的表情:

javascript 演示

const regex = /"(\s+)?([a-z\s]+?)(\s+)?"/gm;
const str = `"name","john","name of john"
"name","       john","name of john"
"       name  ","       john","name of john     "
"       name  ","       john","       name of john     "`;
const subst = `\n$2`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

任务 3

This expression 可能会帮助您为第三个任务设计一个表达式:

(.*?)([a-z\s]+)(.*?)

const regex = /(.*?)([a-z\s]+)(.*?)/gm;
const str = `key = value // comment
key = value with some text // comment`;
const subst = `$2,`;

// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);

console.log('Substitution result: ', result);

【讨论】:

不是我的投票,但请注意答案需要使用 Swift,而不是 JavaScript。 我不会使用a-z。那将不接受带有重音符号的字符串。例如,如果名字是“José”。我只想搜索[^"]+。此外,无需捕获目标字符串前后的空格。【参考方案3】:

一个单一的模式,适用于测试:1...3,在 Swift 中。

let string =
    //"(name,john,string for user name)" //test:1
    //#"("name","       john","name of john")"# //test:2
    "key = value // comment" //test:3

let pattern = #"(?:\w+)(?:\s+\w+)*"# //Swift 5+ only
//let pattern = "(?:\\w+)(?:\\s+\\w+)*"

do 
    let regex = try NSRegularExpression(pattern: pattern)
    let matches = regex.matches(in: string, range: NSRange(0..<string.utf16.count))
    let matchingWords = matches.map 
        String(string[Range($0.range, in: string)!])
    
    print(matchingWords) //(test:3)->["key", "value", "comment"]
 catch 
    print("Regex was bad!")

【讨论】:

【参考方案4】:

让我们考虑一下:

let string = "(name,José,name is José)"

我建议使用正则表达式来查找字符串,其中:

它是完整字符串开头的( 之后或逗号之后的子字符串,即看(?&lt;=^\(|,) 断言的后面; 是不包含,的子串,即[^,]+?; 它是在完整字符串末尾以逗号或) 终止的子字符串,即(?=,|\)$) 的前瞻断言,并且 如果你想让它跳过子字符串前后的空格,也可以输入\s*+

因此:

let pattern = #"(?<=^\(|,)\s*+([^,]+?)\s*+(?=,|\)$)"#
let regex = try! NSRegularExpression(pattern: pattern)
regex.enumerateMatches(in: string, range: NSRange(string.startIndex..., in: string))  match, _, _ in
    if let nsRange = match?.range(at: 1), let range = Range(nsRange, in: string) 
        let substring = String(string[range])
        // do something with `substring` here
    

注意,我使用的是 Swift 5 扩展字符串分隔符(以 #" 开头并以 "# 结尾),因此我不必在字符串中转义我的反斜杠。如果您使用的是 Swift 4 或更早版本,则需要转义这些反斜杠:

let pattern = "(?<=^\\(|,)\\s*+([^,]+?)\\s*+(?=,|\\)$)"

【讨论】:

【参考方案5】:

在了解上述所有 cmets 后,我已经完成了。

let text = """
Capturing and non-capturing groups are somewhat advanced topics. You’ll encounter examples of capturing and non-capturing groups later on in the tutorial
"""

extension String 
            func  rex (_ expr : String)->[String] 
                return try! NSRegularExpression(pattern: expr, options: [.caseInsensitive])
                .matches(in: self, options: [], range: NSRange(location: 0, length: self.count))
                    .map 
                        String(self[Range($0.range, in: self)!])
                
            
        
let r = text.rex("(?:\\w+-\\w+)") // pass any rex

【讨论】:

以上是关于swift中的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

无法让 Swift 中的正则表达式匹配“不包含”

swift中的正则表达式

swift中的正则表达式不适用于此示例?

Swift 将 javascript 正则表达式转换为 ios 正则表达式

在 Swift 中删除字符串中的链接的正则表达式 [重复]

怎样在Swift中使用正则表达式