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é)"
我建议使用正则表达式来查找字符串,其中:
它是完整字符串开头的(
之后或逗号之后的子字符串,即看(?<=^\(|,)
断言的后面;
是不包含,
的子串,即[^,]+?
;
它是在完整字符串末尾以逗号或)
终止的子字符串,即(?=,|\)$)
的前瞻断言,并且
如果你想让它跳过子字符串前后的空格,也可以输入\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中的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章