正则表达式 - 接受 AZ 排除一些固定长度的字母

Regex - Accept AZ excluding some letters for a fixed length

我找不到如何从字符串的固定长度部分排除某些字符

^XXX-\d{4}-(?![XYT])[A-Z]{4}$ 我可以从最后一个字符串的第一个字符中排除 XYT 所以

XXX-0000-AAAA is ok
XXX-0000-XAAA is not ok

我的问题是我不希望在最后一段的任何部分出现 XYT

XXX-0000-AAXA is not ok
XXX-0000-ABXX is not ok
XXX-0000-ABCT is not ok
and so on

我该怎么做?

更确切地说,我补充说XYT是变量,所以固定列表的解决方案可行但不方便

为什么不在最后一部分使用 [A-SU-WZ]{4}? IE。只匹配你想要的字母。

或者,进行重复的前瞻部分:(?:(?![XYT])[A-Z]){4}

有两种 "elegant" 方法可以做到这一点。这个最简单理解就是:

^XXX-\d{4}-((?![XYT])[A-Z]){4}$

这与您所拥有的非常接近,而是将否定前瞻应用到重复中的每个 个字符。

另一种方式是用字符class 相减:

^XXX-\d{4}-[A-Z&&[^XYT]]{4}$

你很少看到使用这种语法,所以如果没有别的东西给你的同事留下深刻印象,使用它可能会很好。

正则表达式: XXX-\d{4}-(?!.*?[XYT])[A-Z]{4}

1. XXX-\d{4} this will match XXX- and then four digits

2. (?!.*?[XYT]) negative look ahead for X Y and T

3. [A-Z]{4} matches 4 characters which can include A-Z.

Regex code demo

这是一个多功能且快速的替代方案

TLDR; ^XXX-[0-9]{4}-[^XYT -@[-²]{4}$

此线程中的问题强调了以几乎需要 "boolean" 方式来表示字符 类 的方式使用正则表达式时的挑战,例如 ['A-Z' 但不是 'XYZ']。出于这个原因,为了其他面临与 OP 描述的类似场景的人的利益,提出了这个答案(作为编辑和更新)。

由于缺少对 ['A-Z' 'XYZ'] 等语法的直接支持;实现这种逻辑并控制正则表达式中重叠表达式的优先顺序的唯一方法是使用 Lookaround Assertions

等功能

然而,低效地应用它们可能会非常昂贵,正如此处其他答案之一所指出的那样。

应用程序在性能标准上的巨大差异使得通用正则表达式无法实现这一点

  • 单个字符串匹配的性能,其中速度差异不明显,可能需要更可靠稳健正则表达式。这可能是代码中 portability 的情况(即几乎每个正则表达式解析器都知道 [[-\`a-~!-@] 是什么意思,但有些人不知道 \W[:punct:] 例如意思。
  • 在尺度的另一端,纳秒是关键,那么人们可能希望在赶上正则表达式之前重新评估过程的许多其他部分,但无论如何,非常 不灵活高性能正则表达式可能是首选,如果系统还不兼容,可以使系统兼容
  • 字符串的多样性对性能有重大影响,因此根据应用程序,可以对字符串的某些部分进行不同的评估
  • 出于同样的原因,如何构建 Lookaround 的决定可能应该根据用例来确定。
  • 如果字符串是数据库的一部分并且搜索是通过 API 或其他内置函数完成的,则可能需要使用特定的语法或格式。
  • 除了匹配表达式之外,不同的正则表达式库、函数、扩展可以改变使用选项完成正则表达式的整个方式。例如,python re.findall() 可以用作具有未知重复长度的 positive lookbehind 的等效操作。
  • 一些实现正则表达式的程序比其他程序快得多。在比较理论步骤时,这不仅可以抵消效率差异。

这里有一个平衡的方法来解决这个问题:

^XXX-[0-9]{4}-[^XYT -@[-²]{4}$

这是一个示例,其中 10000 个字符串匹配 of 10100:https://regex101.com/r/YJ5xME/1

这里是一个例子,其中 100 个字符串匹配 of 10100:https://regex101.com/r/d1l5af/1

两者在 10000 个字符串的性能上没有太大差异,相比之下,这个正则表达式:^XXX-[0-9]{4}-([A-Z](?<=[^XYT])){4}$ 用两倍的时间来匹配 10000 个字符串。

这也与按要求应用排除变量兼容

使用bash的命令行示例:

取一个字符串文件stringfile,内容如:

  • XXX-0000-SNUR
    XXX-0000-FHDZ
    XXX-0000-+439
    XXX-0000-04X9
    XXX-0000-/1Y+
    XXX-0000-X/X9
    XXX-0000-Y6X9
    XXX-0000-XY16
    XXX-0000-0T94
    XXX-0000-++6Y
    XXX-0000-TT+3
    XXX-0000-NLNL
    XXX-0000-QPSE
    

变量的使用$exclude 例如:

  • exclude="XYT"
    egrep "^XXX-[0-9]{4}-([^$exclude[^XYT -@[-²]){4}$" < stringfile

正确匹配:

  • XXX-0000-SNUR
    XXX-0000-FHDZ
    XXX-0000-NLNL
    XXX-0000-QPSE

这也与扩展的正则表达式兼容

  • 用例如 GNU find-iregex(如果处理文件名)
  • egrep (grep -E)
  • 任何支持现代正则表达式的东西,如POSIX 1003.2

我可以在匹配几千行之前只做正确的表达吗?

这就是效率与准确性的结合点。命令行中的示例:

exclude="XYT"
customCharClass="$(
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZ
echo "${alpha[@]}" \
| sed -E -e "s/[$exclude]//g")"

egrep "^XXX-[0-9]{4}-([$customCharClass]){4}$" < stringfile

现在这是应用于字符串文件的正则表达式:

^XXX-[0-9]{4}-([ABCDEFGHIJKLMNOPQRSUVWZ]){4}$ 

(注意没有 X YT

  • 顶部给出的示例说明了易移植性、快速性能以及不涉及扩展字符集的常见用例。
  • 这里的例子,程序决定最有效的搜索条件,保证考虑到所有场景
  • 权衡和性能评估标准是用例。 IE。生成自定义搜索字符串对于一个字符串来说肯定会花费更长的时间,相比之下,在搜索数千个文件时可以忽略不计。

此线程中还有另一个答案补充了此答案。

此正则表达式由@mickmackusa 发布

^X{3}-\d{4}-(?![A-Z]{0,3}[XYT])[A-Z]{4}$

这个正则表达式表现良好,比这个答案中提供的替代方法更干净(但是它确实需要 PCRE)。

这执行 稍微 慢(但绝不是低效或浪费), 保证只产生 [A-Z] 匹配(不包括 XYT)。

这突出表明在设计可能需要 lookarounds

的正则表达式时需要评估特定于应用程序的性能标准

好的,这似乎是我能做出的最有效、最正确的模式:(Demo)

^X{3}-\d{4}-(?![A-Z]{0,3}[XYT])[A-Z]{4}$

我已经设置了一组字符串来匹配 should/does 暴露了此页面上发布的模式中的任何缺陷。我的模式在 176 个步骤中完成了测试并提供了正确的匹配。这使其成为根据 OP 的要求使用负前瞻的最佳模式。

同类比较:

original 190 steps ^XXX-\d{4}-(?![XYT])[A-Z]{4}$ user1875921 Demo

incorrect 300 steps XXX-\d{4}-(?!.*?[XYT])[A-Z]{4} Sahil Gulati Demo

correct 140 steps ^XXX-\d{4}-[ABCDEFGHIJKLMNOPQRSUVWZ]{4}$ [commented] Demo

correct 245 steps ^XXX-\d{4}-((?![XYT])[A-Z]){4}$ Bohemian #1 Demo

correct 279 steps ^XXX-\d{4}-(?:(?![XYT])[A-Z]){4}$ melpomene Demo

n/a - ^XXX-\d{4}-[A-Z&&[^XYT]]{4}$ Bohemian #2