在 Regex 中,如何将重复组的一部分与前一个重复的部分匹配?

How do you match part of a repeating group to a part from a previous repeat, in Regex?

假设我有一个数据存储或归档系统并且我接受一些格式(遗留原因,不是我自己的设计)

例如,我需要接受

abcd.efgh.1234.4567
abcd-efgh-1234-4567
abcd|efgh|1234|4567

但不是

abcd.efgh-1234|4567

基本上我需要对我使用的分隔符保持一致。我正在尝试构建一个可以检查的正则表达式,但我发现它真的很棘手。我已经探索了正则表达式引用并了解它们如何用于查找像 abc-abc-abc 这样的重复,但在我的情况下,我需要它来允许 abcd 部分不同并且只有 确保我有相同的分隔符

这是我目前得到的结果 (link to Regex101);

(([a-z1-9]){4}([\.:|])){3}(([a-z1-9]){4})

我需要以某种方式给出对那个 ([\.:|]) 的反向引用,但我不能把它放在那里,因为它需要自己重复。

在 Regex 中有没有办法做到这一点?

您可以在分隔符第一次出现时捕获它,稍后再反向引用它:

[a-z1-9]{4}([.:|])(?:[a-z1-9]{4}){2}[a-z1-9]{4}  

参见正则表达式 demo

  • [a-z1-9]{4}匹配长度为四个字;
  • ([.:|])匹配并捕获分隔符;
  • (?:[a-z1-9]{4}){2}捕获第二个和第三个模式,分隔符参考上面捕获的分隔符;
  • [a-z1-9]{4}匹配最后一个词;

您的正则表达式可以是 \w+([.|-])\w+\d+\d+ 请参阅:example 1

它对第一个遇到的分隔符(“|”、“.”或“-”)使用反向引用 \1

测试:

$ cat repeat.txt
abcd.efgh.1234.4567
abcd-efgh-1234-4567
abcd|efgh|1234|4567
abcd.efgh-1234|4567

结果:

$ grep -P '\w+([.|-])\w+\d+\d+' repeat.txt
abcd.efgh.1234.4567
abcd-efgh-1234-4567
abcd|efgh|1234|4567

或者,更通用:

$ grep -P '\w+(\W)\w+(\w+)+' repeat.txt
abcd.efgh.1234.4567
abcd-efgh-1234-4567
abcd|efgh|1234|4567

参见:example 2。不过,最后一个的问题可能是重复组仅捕获最后一次出现的事件。