Swift replace子字符串regex

dw1jzc5e  于 2023-09-30  发布在  Swift
关注(0)|答案(9)|浏览(167)

我尝试使用正则表达式来替换字符串中所有出现的英国汽车注册。
当字符串与正则表达式完全匹配时,下面的swift代码可以完美地工作。

  1. var myString = "DD11 AAA"
  2. var stringlength = countElements(myString)
  3. var ierror: NSError?
  4. var regex:NSRegularExpression = NSRegularExpression(pattern: "^([A-HK-PRSVWY][A-HJ-PR-Y])\\s?([0][2-9]|[1-9][0-9])\\s?[A-HJ-PR-Z]{3}$", options: NSRegularExpressionOptions.CaseInsensitive, error: &ierror)!
  5. var modString = regex.stringByReplacingMatchesInString(myString, options: nil, range: NSMakeRange(0, stringlength), withTemplate: "XX")
  6. print(modString)

结果为XX
但是,以下操作不起作用,字符串不会被修改

  1. var myString = "my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB"
  2. var stringlength = countElements(myString)
  3. var ierror: NSError?
  4. var regex:NSRegularExpression = NSRegularExpression(pattern: "^([A-HK-PRSVWY][A-HJ-PR-Y])\\s?([0][2-9]|[1-9][0-9])\\s?[A-HJ-PR-Z]{3}$", options: NSRegularExpressionOptions.CaseInsensitive, error: &ierror)!
  5. var modString = regex.stringByReplacingMatchesInString(myString, options: nil, range: NSMakeRange(0, stringlength), withTemplate: "XX")
  6. print(modString)

结果为my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB
有人能给予我指点吗?

rks48beu

rks48beu1#

您需要删除^$锚。
^表示 * 字符串的开始 *,$表示 * 字符串的结束 *(或行,取决于选项)。这就是为什么你的第一个例子工作:在第一个测试字符串中,字符串的开头实际上跟随着您的模式,并以它结束。
在第二个测试字符串中,在字符串的中间发现了模式,因此^...不能应用。如果您只删除^,则$将应用于注册号的第二次出现,输出将为my car reg 1 - DD11 AAA my car reg 2 - XX

  1. let myString = "my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB"
  2. let regex = try! NSRegularExpression(pattern: "([A-HK-PRSVWY][A-HJ-PR-Y])\\s?([0][2-9]|[1-9][0-9])\\s?[A-HJ-PR-Z]{3}", options: NSRegularExpression.Options.caseInsensitive)
  3. let range = NSMakeRange(0, myString.count)
  4. let modString = regex.stringByReplacingMatches(in: myString, options: [], range: range, withTemplate: "XX")
  5. print(modString)
  6. // Output: "my car reg 1 - XX my car reg 2 - XX"
6ss1mwsb

6ss1mwsb2#

让我们使用一个类扩展来用Swift 3语法 Package 它:

  1. extension String {
  2. mutating func removingRegexMatches(pattern: String, replaceWith: String = "") {
  3. do {
  4. let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
  5. let range = NSRange(location: 0, length: count)
  6. self = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith)
  7. } catch { return }
  8. }
  9. }
  10. var phoneNumber = "+1 07777777777"
  11. phoneNumber.removingRegexMatches(pattern: "\\+\\d{1,4} (0)?")

结果为7777777777(从而从电话号码中删除国家代码)

mm5n2pyu

mm5n2pyu3#

Swift 4.2更新

  1. let myString = "my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB"
  2. if let regex = try? NSRegularExpression(pattern: "([A-HK-PRSVWY][A-HJ-PR-Y])\\s?([0][2-9]|[1-9][0-9])\\s?[A-HJ-PR-Z]{3}", options: .caseInsensitive) {
  3. let modString = regex.stringByReplacingMatches(in: myString, options: [], range: NSRange(location: 0, length: myString.count), withTemplate: "XX")
  4. print(modString)
  5. }
qnakjoqk

qnakjoqk4#

Swift 2.1更新:

  1. var myString = "my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB"
  2. if let regex = try? NSRegularExpression(pattern: "([A-HK-PRSVWY][A-HJ-PR-Y])\\s?([0][2-9]|[1-9][0-9])\\s?[A-HJ-PR-Z]{3}", options: .CaseInsensitive) {
  3. let modString = regex.stringByReplacingMatchesInString(myString, options: .WithTransparentBounds, range: NSMakeRange(0, myString.characters.count), withTemplate: "XX")
  4. print(modString)
  5. }
nwnhqdif

nwnhqdif5#

警告

不要像上面引用的所有例子那样使用NSRange(location: 0, length: myString.count)
使用NSRange(myString.startIndex..., in: myString)代替!
.count将把\r\n这样的换行符算作一个字符-这可能会导致缩短的,因此无效的,不匹配整个字符串的NSRange。
(.length should work)

uyto3xhc

uyto3xhc6#

简单扩展:

  1. extension String {
  2. func replacingRegex(
  3. matching pattern: String,
  4. findingOptions: NSRegularExpression.Options = .caseInsensitive,
  5. replacingOptions: NSRegularExpression.MatchingOptions = [],
  6. with template: String
  7. ) throws -> String {
  8. let regex = try NSRegularExpression(pattern: pattern, options: findingOptions)
  9. let range = NSRange(startIndex..., in: self)
  10. return regex.stringByReplacingMatches(in: self, options: replacingOptions, range: range, withTemplate: template)
  11. }
  12. }

对其他答案的优势

  • 暴露了向调用者抛出error
  • 为方便使用,向调用者提供了默认的查找选项
  • 为便于使用,向调用者公开了默认的替换选项
  • 修复原答案中range*BUG *
展开查看全部
rqqzpn5f

rqqzpn5f7#

使用pattern: "^ ... $",您已经指定了模式锚定到字符串的开始和结束,换句话说,* 整个 * 字符串必须匹配模式。只需从模式中删除^$,您将获得预期的结果。

t9aqgxwy

t9aqgxwy8#

所有在答案中使用.count的答案的注意事项:
在操作目标范围具有代理配对字符的情况下,这将导致问题。
请使用.utf16.count修改您的答案。
下面是瑞安·布罗迪的回答。使用Swift 5.5。

  1. private extension String {
  2. mutating func regReplace(pattern: String, replaceWith: String = "") {
  3. do {
  4. let regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive, .anchorsMatchLines])
  5. let range = NSRange(location: 0, length: self.utf16.count)
  6. self = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith)
  7. } catch { return }
  8. }
  9. }

**更新:**如果考虑@coyer的担忧:

  1. private extension String {
  2. mutating func regReplace(pattern: String, replaceWith: String = "") {
  3. do {
  4. let regex = try NSRegularExpression(pattern: pattern, options: [.caseInsensitive, .anchorsMatchLines])
  5. let range = NSRange(self.startIndex..., in: self)
  6. self = regex.stringByReplacingMatches(in: self, options: [], range: range, withTemplate: replaceWith)
  7. } catch { return }
  8. }
  9. }

**还:**致@Martin R':只要你在正则表达式选项中启用了“.anchorsMatchLines”,就可以在正则表达式中使用^和$。我已经在上面的代码块中应用了这个选项。

展开查看全部
olqngx59

olqngx599#

Swift 5.7更新

  1. let myString = "my car reg 1 - DD11 AAA my car reg 2 - AA22 BBB"
  2. let regex = #/([A-HK-PRSVWY][A-HJ-PR-Y])\s?([0][2-9]|[1-9][0-9])\s?[A-HJ-PR-Z]{3}/#
  3. let modString = myString.replacing(regex.ignoresCase(), with: "XX")
  4. print(modString)
  5. // Output: "my car reg 1 - XX my car reg 2 - XX"

相关问题