NSRegularExpression和重复模式

时间:2016-01-19 18:43:41

标签: ios regex xcode

我正在编写一个通过TCP接收消息块的应用程序。消息块由以下内容组成:

  • 固定标题<<:--!!
  • 提供消息长度的6位数字
  • 消息本身

使用NSRegularExpression从收到的数据中提取消息听起来合乎逻辑,所以我最终在操场上使用了以下代码,实现了对收到的数据字符串的处理:

import UIKit

struct Constants {
    static let messageHeaderPattern = "<<:--!!(\\d{6})(.+)"
}

let receivedData = "<<:--!!000010My message"

let regex = try! NSRegularExpression(pattern: Constants.messageHeaderPattern, options: [])  // Define the regular expression
let range = NSMakeRange(0, receivedData.characters.count)                          // Define the range (all the string)
let matches = regex.matchesInString(receivedData, options: [], range: range)       // Get the matches

print("Number of matches: \(matches.count)")

for match in matches {

    let locationOfMessageLength = match.rangeAtIndex(1).location
    let expectedLengthOfMessage = Int(receivedData.substringWithRange(Range(start: receivedData.startIndex.advancedBy(locationOfMessageLength),
        end: receivedData.startIndex.advancedBy(locationOfMessageLength + 6))))

    let locationOfMessage = match.rangeAtIndex(2).location
    let lengthOfMessage = match.rangeAtIndex(2).length
    let data = receivedData.substringWithRange(Range(start: receivedData.startIndex.advancedBy(locationOfMessage),
        end: receivedData.startIndex.advancedBy(locationOfMessage + lengthOfMessage)))

    // data contains "My message"

}

此代码运行良好,但前提是字符串中只有一条消息。为了使它适用于多个消息,我更改了正则表达式:

static let messageHeaderPattern = "(?:<<:--!!(\\d{6})(.+))+"

和收到的数据:

let receivedData = "<<:--!!000010My message<<:--!!000014Second message"

但仍然只有一个匹配,数据包含My message<<:--!!000014Second message

我的正则表达式出了什么问题?

3 个答案:

答案 0 :(得分:1)

该消息甚至可能包含^<<:--!!(\d{6}),因此我认为您无法单独使用正则表达式进行此操作,因此安全的解决方案就是。

  1. <<:--!!\d{6}的正则表达式提取长度N
  2. 从第13个字符串中输出N个字符
  3. 重复
  4. 如果你想生活危险并且确信(?<=<<:--!!\d{6})(.*?)(?=<<:--!!\d{6}|$) 永远不会出现在消息中,那么这个正则表达式就可以解决问题。

    map.clear()

    请记住,如果分隔符出现在字符串中,会搞乱,你应该使用我的第一个例子中的方法来保证安全。

答案 1 :(得分:0)

尝试使用模式static let messageHeaderPattern = "<<:--!!(\\d{6})(.+?)(?!<<:--!!)"

答案 2 :(得分:0)

尝试更多地过滤邮件本身,因此(。*)不包含第二条消息:

con_P