负向回顾,可选后缀,无重复

huangapple go评论51阅读模式
英文:

Negative lookbehind with optional suffix without duplication

问题

I am writing regex that finds all stings with these conditions:

  • not starting with foo/ or bar/ or with foo (end of line) or bar (end of line)
  • not ending with /baz or /qux and not ending with /baz/ or /qux/

Examples that should not match:

foo
bar/nomatch
/nomatch/baz
nomatch/baz/

Examples should match:

foomatch
bazmatch
/baz/match

The regex I came up with combines a negative lookahead and a negative lookbehind:

/(?!(foo|bar)(\/|$)).*(?<!(\/)(baz|qux)(\/|$))/gm

My problem: the negative lookbehind needs to have a fixed width (ie: I cannot use (\/|$) to check for an optional slash at the end of the string). I could solve this by creating the following rule: /(?!(foo|bar)(\/|$)).*(?<!(\/)(baz|qux))(?<!(\/)(baz|qux)\/)/gm, which uses baz and qux twice. Is there another way to solve this without this duplication?

For an interactive example, see: https://regex101.com/r/bIosD0/1

英文:

I am writing regex that finds all stings with these conditions:

  • not starting with foo/ or bar/ or with foo (end of line) or bar (end of line)
  • not ending with /baz or /qux and not ending with /baz/ or /qux/

Examples that should not match:

foo
bar/nomatch
/nomatch/baz
nomatch/baz/

Examples should match:

foomatch
bazmatch
/baz/match

The regex I came up with combines a negative lookahead and a negative lookbehind:

/(?!(foo|bar)(\/|$)).*(?<!(\/)(baz|qux)(\/|$))/gm

My problem: the negative lookbehind needs to have a fixed width (ie: I cannot use (\/|$) to check for an optional slash at the end of the string). I could solve this by creating the following rule: /(?!(foo|bar)(\/|$)).*(?<!(\/)(baz|qux))(?<!(\/)(baz|qux)\/)/gm, which uses baz and qux twice. Is there another way to solve this without this duplication?

For an interactive example, see: https://regex101.com/r/bIosD0/1

答案1

得分: 4

你可以去掉后顾条件,然后要么添加另一个负向前瞻,要么在不同条件之间使用一个交替。假设你还想禁止单独出现的 quxbaz

^(?!(?:foo|bar)(?:\/|$)|(?:.*\/)?(?:baz|qux)\/?$).+

^ 开始(?! 负向前瞻 lookahead ) 包含两个条件:

  1. (?:foo|bar)(?:\/|$),你已经拥有的部分,例如 不允许 foo/...foobar 同理)
  2. |(?:.*\/)?(?:baz|qux)\/?$ 不允许 bazbaz/,前面可以有一个可选的 .*\/任意数量任意字符 后跟一个斜杠),以进一步禁止诸如 .../baz/.../baz$ 结尾

在 regex101 上查看此演示

我使用了 (?: 非捕获组 ) 来进行交替,因为不需要捕获任何内容。

英文:

You can drop the lookbehind and either add another negative lookahead or use one and alternate inside between different conditions. Assuming you also want to disallow qux and baz alone.

^(?!(?:foo|bar)(?:\/|$)|(?:.*\/)?(?:baz|qux)\/?$).+

At ^ start the (?! negative lookahead ) contains two conditions:

  1. (?:foo|bar)(?:\/|$) what you got already, e.g. no foo/..., foo (same for bar)
  2. |(?:.*\/)?(?:baz|qux)\/?$ OR no baz, baz/ preceded by an optional .*\/ (any amount of any characters followed by a slash) to further disallow such as .../baz/, .../baz at $ end.

See this demo at regex101

I used (?: non-capturing groups ) for alternations because nothing needs to be captured.

huangapple
  • 本文由 发表于 2023年5月29日 19:22:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76356909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定