我有一个字符串"323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography",我想使用regex表达式[0-9][0-9][0-9][A-Z][A-Z][A-Z]来拆分这个字符串,以便函数返回数组:
Array =
["323 ECO Economics Course ", "451 ENG English Course", "789 Mathematical Topography"]我怎么用斯威夫特来做这件事呢?
编辑我的问题与链接的问题不同。我意识到可以使用myString.components(separatedBy: "splitting string")快速拆分字符串,问题是这个问题不能解决如何使splitting string成为正则表达式。我试过使用mystring.components(separatedBy: "[0-9][0-9][0-9][A-Z][A-Z][A-Z]", options: .regularExpression),但这不起作用。
如何使separatedBy:部分成为正则表达式?
发布于 2017-02-27 02:07:37
Swift到目前为止还没有本机正则表达式。但是Foundation提供了NSRegularExpression。
import Foundation
let toSearch = "323 ECO Economics Course 451 ENG English Course 789 MAT Mathematical Topography"
let pattern = "[0-9]{3} [A-Z]{3}"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
// NSRegularExpression works with objective-c NSString, which are utf16 encoded
let matches = regex.matches(in: toSearch, range: NSMakeRange(0, toSearch.utf16.count))
// the combination of zip, dropFirst and map to optional here is a trick
// to be able to map on [(result1, result2), (result2, result3), (result3, nil)]
let results = zip(matches, matches.dropFirst().map { Optional.some($0) } + [nil]).map { current, next -> String in
let range = current.rangeAt(0)
let start = String.UTF16Index(range.location)
// if there's a next, use it's starting location as the ending of our match
// otherwise, go to the end of the searched string
let end = next.map { $0.rangeAt(0) }.map { String.UTF16Index($0.location) } ?? String.UTF16Index(toSearch.utf16.count)
return String(toSearch.utf16[start..<end])!
}
dump(results)运行这将输出
▿ 3 elements
- "323 ECO Economics Course "
- "451 ENG English Course "
- "789 MAT Mathematical Topography"发布于 2017-02-27 01:57:47
您可以使用regex "\\b[0-9]{1,}[a-zA-Z ]{1,}"和来自answer的这个扩展来使用文字、caseInsensitive或regularExpression搜索获取字符串的所有范围:
extension StringProtocol {
func ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>] {
var result: [Range<Index>] = []
var startIndex = self.startIndex
while startIndex < endIndex,
let range = self[startIndex...].range(of: string, options: options) {
result.append(range)
startIndex = range.lowerBound < range.upperBound ? range.upperBound :
index(range.lowerBound, offsetBy: 1, limitedBy: endIndex) ?? endIndex
}
return result
}
}let inputString = "323 ECO Economics Course 451 ENG English Course 789 Mathematical Topography"
let courses = inputString.ranges(of: "\\b[0-9]{1,}[a-zA-Z ]{1,}", options: .regularExpression).map { inputString[$0].trimmingCharacters(in: .whitespaces) }
print(courses) // ["323 ECO Economics Course", "451 ENG English Course", "789 Mathematical Topography"]发布于 2021-03-21 22:43:43
我需要这样的东西,并且应该更像JS String.prototype.split(pat: RegExp)或Rust's String.splitn(pat: String.splitn<‘a>),但是使用Regex。
extension NSRegularExpression {
convenience init(_ pattern: String) {...}
/// An array of substring of the given string, separated by this regular expression, restricted to returning at most n items.
/// If n substrings are returned, the last substring (the nth substring) will contain the remainder of the string.
/// - Parameter str: String to be matched
/// - Parameter n: If `n` is specified and n != -1, it will be split into n elements else split into all occurences of this pattern
func splitn(_ str: String, _ n: Int = -1) -> [String] {
let range = NSRange(location: 0, length: str.utf8.count)
let matches = self.matches(in: str, range: range);
var result = [String]()
if (n != -1 && n < 2) || matches.isEmpty { return [str] }
if let first = matches.first?.range {
if first.location == 0 { result.append("") }
if first.location != 0 {
let _range = NSRange(location: 0, length: first.location)
result.append(String(str[Range(_range, in: str)!]))
}
}
for (cur, next) in zip(matches, matches[1...]) {
let loc = cur.range.location + cur.range.length
if n != -1 && result.count + 1 == n {
let _range = NSRange(location: loc, length: str.utf8.count - loc)
result.append(String(str[Range(_range, in: str)!]))
return result
}
let len = next.range.location - loc
let _range = NSRange(location: loc, length: len)
result.append(String(str[Range(_range, in: str)!]))
}
if let last = matches.last?.range, !(n != -1 && result.count >= n) {
let lastIndex = last.length + last.location
if lastIndex == str.utf8.count { result.append("") }
if lastIndex < str.utf8.count {
let _range = NSRange(location: lastIndex, length: str.utf8.count - lastIndex)
result.append(String(str[Range(_range, in: str)!]))
}
}
return result;
}
}通过下列测试
func testRegexSplit() {
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn("My . Love"), ["My", "Love"])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn("My . Love . "), ["My", "Love", ""])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn(" . My . Love"), ["", "My", "Love"])
XCTAssertEqual(NSRegularExpression("\\s*[.]\\s+").splitn(" . My . Love . "), ["", "My", "Love", ""])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX"), ["", "My", "", "Love", ""])
}
func testRegexSplitWithN() {
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 1), ["xXMyxXxXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", -1), ["", "My", "", "Love", ""])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 2), ["", "MyxXxXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 3), ["", "My", "xXLovexX"])
XCTAssertEqual(NSRegularExpression("xX").splitn("xXMyxXxXLovexX", 4), ["", "My", "", "LovexX"])
}
func testNoMatches() {
XCTAssertEqual(NSRegularExpression("xX").splitn("MyLove", 1), ["MyLove"])
XCTAssertEqual(NSRegularExpression("xX").splitn("MyLove"), ["MyLove"])
XCTAssertEqual(NSRegularExpression("xX").splitn("MyLove", 3), ["MyLove"])
}https://stackoverflow.com/questions/42476395
复制相似问题