只有当整行与正则表达式匹配时才替换模式。

4
我相信这个问题有一个简单的解决方案,但我似乎无法得到正确的答案:
我想在一行中替换特定的模式,只有整行匹配正则表达式时才能替换。 因此,在我的情况下,只有当整行是数字和管道符号|时,三个管道符号|才应被替换为下划线_
|||10|||-80|||-120|||400           ---> replace
|||10|||asdf|||-120|||400          ---> don't replace
|||10|||-80|||400                  ---> replace
|||10|||-80|||-120|||400|||test    ---> don't replace

期望结果:

___10___-80___-120___400
|||10|||asdf|||-120|||400
___10___-80___400
|||10|||-80|||-120|||400|||test

我的尝试:

\|\|\|(?=\-?\d+)

如果后面跟着数字,它会按预期替换管道符号,但当然也会在“无效”的行中进行替换。

^(\|\|\|\-?\d+){1,}$

这个模式匹配整行,所以我不能只替换管道符。

我理解为什么我的模式不起作用,也许我只需要用两次操作就可以了,但感觉完全有可能做到。


你要找的概念叫做“捕获组”。 - Ant P
1个回答

5

没有更多的细节,看起来你可以使用

(?<=^(?:\|{3}-?\d+)*)\|{3}(?=-?\d+(?:\|{3}-?\d+)*$)

或者,如果你需要在一个较大的字符串中处理

(?m)(?<=^(?:\|{3}-?\d+)*)\|{3}(?=-?\d+(?:\|{3}-?\d+)*\r?$)

请查看正则表达式演示细节:
  • (?<=^(?:\|{3}-?\d+)*):正向后行断言,要求当前位置的左边紧邻的是:
    • ^:字符串的开头锚点
    • (?:\|{3}-?\d+)*:被 3 个管道符 | 分隔开的可选连续数字(可以有一个可选的减号 -)。
  • \|{3}:3个管道符 |
  • (?=-?\d+(?:\|{3}-?\d+)*$):正向前瞻,要求当前位置的右边紧邻的是
    • -?\d+:一个可选的减号 - 后面跟着一个或多个数字
    • (?:\|{3}-?\d+)*:三个连续的管道符 | 后面跟着可选的连续数字(可以有一个减号 -)。
    • $:字符串的结尾锚点。

enter image description here

C#:

var res = Regex.Replace(s, @"(?<=^(?:\|{3}-?\d+)*)\|{3}(?=-?\d+(?:\|{3}-?\d+)*$)", "___", RegexOptions.ECMAScript);

使用RegexOptions.ECMAScript标志可以使\d仅匹配ASCII数字。


这实际上是一个问题,但我希望你不介意我直接向你提问,Wiktor - 我正在尝试回答这个问题,并想到了这个(?<=^[\d|-]*)\|\|\|(?=[-\d|]*$)。然而,REGEX STORM不会“接受” $,即使设置了多行也是如此。可以通过将其更改为 (?:$|\r) 来解决,但是...有什么想法吗? - SamWhan
@ClasG:这里的换行风格是\r\n,但在.NET正则表达式中,$只匹配\n之前的内容,因此,在RegexStorm中使用多行字符串进行测试时,必须在$之前添加\r?。顺便说一句,如果验证很重要,我不会使用(?<=^[\d|-]*)\|\|\|(?=[-\d|]*$)(这将替换类似于||||||||||||||的三个|的字符串)。 - Wiktor Stribiżew
知道你会有解释,谢谢W!好知道。 - SamWhan

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