如何在 Swift 中使用正则表达式来捕获冒号之间的字符串
How to use regex in Swift to capture string between colons
有一些任意长度的字符串 return 从后端编辑为 "junkasdojf :text:"
我如何使用正则表达式 return 一个干净的字符串作为 ":text:"
(必须包含冒号)
最好是一种快速处理此问题的方法。之前没有使用过正则表达式,但我读到它是解决这个问题的唯一方法,除了进行令人讨厌的拆分和重建。
这是我目前的情况,但不确定如何取得进展
let regex = try? NSRegularExpression(pattern: ":[a-z]:", options: .caseInsensitive)
使用range(of:options:)
会更简单。
let someStr = "junkasdojf :text:"
if let substrRange = someStr.range(of: ":[a-zA-Z]+:", options: .regularExpression) {
print("Match = \(someStr[substrRange])")
} else {
print("No match")
}
以下将匹配多次出现
// \w matches any word character such as [a-zA-Z0-9_]
let regex = try! NSRegularExpression(pattern: ":\w+:")
let nsString: NSString = "junkasdojf :text: flkasdj junkasdojf :two:"
let matches = regex.matches(in: nsString as String, options: [], range: NSMakeRange(0, nsString.length))
for match in matches {
print(nsString.substring(with: match.range))
}
更通用的方法是使用捕获组:
let pattern = "junkasdojf\s*(:[^:]*:)"
示例 Swift 代码:
let str = "Some string here, junkasdojf :text: and more here"
let pattern = "junkasdojf\s*(:[^:]*:)"
do {
let regex = try NSRegularExpression(pattern: pattern)
if let match = regex.firstMatch(in: str, range: NSRange(str.startIndex..., in: str)) {
let result = str[Range(match.range(at: 1), in: str)!]
print(String(result))
}
} catch { print(error) }
参见 the regex demo。
在这里,junkasdojf
匹配您需要的字符串的左侧上下文子字符串,\s*
匹配 0+ 个空格,(:[^:]*:)
将冒号捕获到组 1 中, :
以外的任何 0+ 个字符,然后是 :
.
或者,如果 junkasdojf
和 :
之间的空格数不能超过某个最大阈值,您可以使用基于 constrained-width lookbehind解决方案:
let s = "Some string here, junkasdojf :text: and more here"
if let rng = s.range(of: ":(?<=junkasdojf\s{0,1000}:)[^:]*:", options: .regularExpression) {
print(s[rng])
}
这在 regex101 上不起作用,因为它不支持 ICU 正则表达式风格,但这假设 junkasdojf
和下一个 :
之间的空格不能超过 1000 个。 :(?<=junkasdojf\s{0,1000}:)[^:]*:
匹配 :
,然后确保 junkasdojf
后跟 0 到 1000 个空格和 :
(这是锚定到第一个 :
所必需的) ) 然后 [^:]*
匹配 :
以外的零个或多个字符,然后 :
匹配 :
.
此外,如果您对可能的最短正则表达式感兴趣但效率较低的解决方案,您可以使用
正则表达式替换输入字符串
let s = "Some string here, junkasdojf :text: and more here"
let result = s.replacingOccurrences(of: "(?s).*junkasdojf\s*(:[^:]*:).*", with: "", options: .regularExpression, range: nil)
print(result)
输出::text:
.
详情
(?s)
- 允许 .
匹配换行字符 的修饰符
.*
- 任何 0+ 个字符尽可能多
junkasdojf
- 一个子字符串
\s*
- 0+ 个空格
(:[^:]*:)
- 捕获组 1 (</code>):冒号、除 <code>:
、冒号 以外的 0 个或更多字符
.*
- 任何 0+ 个字符尽可能多
rmaddy 的答案对于一个简单的、非重复的任务来说是一个更好的方法,当你不介意在 Swift 代码中使用 NSString
时,AamirR 的答案似乎是正确的解决方案。
但是 NSRegularExpression
和 Swift String
的基本用法是这样的:
let str = "junkasdojf :text:"
//You can use `try!` when you are sure your pattern is valid.
//And do not miss `+` after `[a-z]`.
let regex = try! NSRegularExpression(pattern: ":[a-z]+:", options: .caseInsensitive)
//Use `str.utf16.count`, not `str.count`.
if let match = regex.firstMatch(in: str, range: NSRange(0..<str.utf16.count)) {
//Use `Range.init(_:in:)` to convert `NSRange` to `Range<String.Index>`.
let range = Range(match.range, in: str)!
//When you can accept `Substring`, `String.init(_:)` is not needed.
let matchingStr = String(str[range])
print(matchingStr) //->:text:
} else {
print("*NO mathes*")
}
有一些任意长度的字符串 return 从后端编辑为 "junkasdojf :text:"
我如何使用正则表达式 return 一个干净的字符串作为 ":text:"
(必须包含冒号)
最好是一种快速处理此问题的方法。之前没有使用过正则表达式,但我读到它是解决这个问题的唯一方法,除了进行令人讨厌的拆分和重建。
这是我目前的情况,但不确定如何取得进展
let regex = try? NSRegularExpression(pattern: ":[a-z]:", options: .caseInsensitive)
使用range(of:options:)
会更简单。
let someStr = "junkasdojf :text:"
if let substrRange = someStr.range(of: ":[a-zA-Z]+:", options: .regularExpression) {
print("Match = \(someStr[substrRange])")
} else {
print("No match")
}
以下将匹配多次出现
// \w matches any word character such as [a-zA-Z0-9_]
let regex = try! NSRegularExpression(pattern: ":\w+:")
let nsString: NSString = "junkasdojf :text: flkasdj junkasdojf :two:"
let matches = regex.matches(in: nsString as String, options: [], range: NSMakeRange(0, nsString.length))
for match in matches {
print(nsString.substring(with: match.range))
}
更通用的方法是使用捕获组:
let pattern = "junkasdojf\s*(:[^:]*:)"
示例 Swift 代码:
let str = "Some string here, junkasdojf :text: and more here"
let pattern = "junkasdojf\s*(:[^:]*:)"
do {
let regex = try NSRegularExpression(pattern: pattern)
if let match = regex.firstMatch(in: str, range: NSRange(str.startIndex..., in: str)) {
let result = str[Range(match.range(at: 1), in: str)!]
print(String(result))
}
} catch { print(error) }
参见 the regex demo。
在这里,junkasdojf
匹配您需要的字符串的左侧上下文子字符串,\s*
匹配 0+ 个空格,(:[^:]*:)
将冒号捕获到组 1 中, :
以外的任何 0+ 个字符,然后是 :
.
或者,如果 junkasdojf
和 :
之间的空格数不能超过某个最大阈值,您可以使用基于 constrained-width lookbehind解决方案:
let s = "Some string here, junkasdojf :text: and more here"
if let rng = s.range(of: ":(?<=junkasdojf\s{0,1000}:)[^:]*:", options: .regularExpression) {
print(s[rng])
}
这在 regex101 上不起作用,因为它不支持 ICU 正则表达式风格,但这假设 junkasdojf
和下一个 :
之间的空格不能超过 1000 个。 :(?<=junkasdojf\s{0,1000}:)[^:]*:
匹配 :
,然后确保 junkasdojf
后跟 0 到 1000 个空格和 :
(这是锚定到第一个 :
所必需的) ) 然后 [^:]*
匹配 :
以外的零个或多个字符,然后 :
匹配 :
.
此外,如果您对可能的最短正则表达式感兴趣但效率较低的解决方案,您可以使用
正则表达式替换输入字符串let s = "Some string here, junkasdojf :text: and more here"
let result = s.replacingOccurrences(of: "(?s).*junkasdojf\s*(:[^:]*:).*", with: "", options: .regularExpression, range: nil)
print(result)
输出::text:
.
详情
(?s)
- 允许.
匹配换行字符 的修饰符
.*
- 任何 0+ 个字符尽可能多junkasdojf
- 一个子字符串\s*
- 0+ 个空格(:[^:]*:)
- 捕获组 1 (</code>):冒号、除 <code>:
、冒号 以外的 0 个或更多字符
.*
- 任何 0+ 个字符尽可能多
rmaddy 的答案对于一个简单的、非重复的任务来说是一个更好的方法,当你不介意在 Swift 代码中使用 NSString
时,AamirR 的答案似乎是正确的解决方案。
但是 NSRegularExpression
和 Swift String
的基本用法是这样的:
let str = "junkasdojf :text:"
//You can use `try!` when you are sure your pattern is valid.
//And do not miss `+` after `[a-z]`.
let regex = try! NSRegularExpression(pattern: ":[a-z]+:", options: .caseInsensitive)
//Use `str.utf16.count`, not `str.count`.
if let match = regex.firstMatch(in: str, range: NSRange(0..<str.utf16.count)) {
//Use `Range.init(_:in:)` to convert `NSRange` to `Range<String.Index>`.
let range = Range(match.range, in: str)!
//When you can accept `Substring`, `String.init(_:)` is not needed.
let matchingStr = String(str[range])
print(matchingStr) //->:text:
} else {
print("*NO mathes*")
}