使用变量(而不是固定的)字符串子组件的快速正则表达式

4

是否有可能创建一个可重用的 Swift 5.8+ Regex 模式,其中包含一个变量(非固定)组件?如果是,如何实现?

从概念上讲,考虑一种使用关键字变量作为正则表达式的一部分的用例。这类似于在 String 类型中的插值。

func example(keyword: String) {
    // non-functional concept shorthand
    var regex = /…\(keyword)…/
    // do something with regex 
}

很可能一个/…/正则表达式文字没有支持这种方法的语法。并且,\(…) String插值语法和正则表达式(…)捕获语法之间的相似性可能会引发问题。

相反地,是否可以使用其中几种较新的(非NSRegularExpression)正则表达式定义方法来支持可变的String子组件?


2
看起来这是不可能的。不支持字符串插值被明确提到作为/.../语法背后的动机因素之一,以区别于现有的"...": "它将与其他字符串字面量特性(如插值)不兼容。" SE-0354 正则表达式字面量 - Alexander
2
看起来这是不可能的。不支持字符串插值被明确提及为/.../语法背后的动机因素之一,这是为了避免与其他字符串字面量特性(比如插值)不兼容。SE-0354 正则表达式字面量 - undefined
@Alexander 谢谢您提供源文件链接,其中提供了在正则表达式字面量中排除字符串特性的设计考虑。这个信息将解决方案搜索范围缩小到了新的 Swift 正则表达式实现中的 RegexBuilder - marc-medley
正则表达式构建器并不是更新的,它和正则表达式字面量使用相同的实现。只是一个更加便携,而另一个更加表达力强。 - Alexander
@Alexander 明白了。所谓的“新版”是指与“旧版”NSRegularExpression(macOS10.7+,…)相对应的正则表达式字面量和RegexBuilder(macOS 13+,…)这一组正则表达式功能。 - marc-medley
@Alexander 明白了。所谓的“新的”是指与“旧的”NSRegularExpression(macOS10.7+,…)相对应的正则表达式字面量和RegexBuilder(macOS 13+,…)的一组正则表达式功能。 - undefined
1个回答

6
RegexBuilder 提供了一种方便的方法来构建正则表达式。例如:
import RegexBuilder

let string = "prefixandthissuffix"

func example(keyword: String) {
    // non-functional concept shorthand
    var regex = Regex {
        "prefix"
        keyword
        "suffix"
    }

    if let match = string.wholeMatch(of: regex) {
        print(match.output)
    } else {
        print("\(keyword): nomatch")
    }
}

example(keyword: "andthis")  // prints match
example(keyword: "andthat")  // nomatch

请注意,每次关键字字符串需要更改时,都需要重新构建正则表达式(Regex)。动态重建可以封装在一个函数中。
func quotedRegex(keyword: String) -> Regex<Substring> {
    let regex = Regex {
        /"/
        keyword
        /"/
    }
    return regex
}

let string = "{\"key1\":\"value\"}"
for word in ["key1", "KEY1", "key2"] {
    var regex = quotedRegex(keyword: word)
    regex = regex.ignoresCase() // transformed
    if let match = string.firstMatch(of: regex) {
        print("\(word) matched \(match.output)")
    } else {
        print("\(word) not matched")
    }
}

// print:
//   key1 matched "key1"
//   KEY1 matched "key1"
//   key2 not matched

我在你的答案中添加了一些细节,以说明当前的Regex没有可动态更改的可变String子组件。因此,每次字符串组件更改都需要重新构建Regex。尽管如此,这个答案确实提供了一个有用的解决方案来解决所述的问题。 - marc-medley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接