【问题标题】:Combining Regex 'in between' AND 'do not contain'结合正则表达式“介于”和“不包含”
【发布时间】:2021-03-27 09:39:08
【问题描述】:

我尝试将两个正则表达式与AND 结合,但尝试失败。

  1. 在 '[[' 和 (']]' 或 '|') 之间连续选取任何内容:
(?<=(\[\[))(.*?)(?=(\||(\]\])))
  1. 不包含“http”:
^(?:(?!http).)*$

我最好的尝试是

(?=(?<=(\[\[))(.*?)(?=(\||(\]\]))))(?=^(?:(?!http).)*$).*$ 

关注https://stackoverflow.com/a/870506,但它不起作用。

我的目标是获取 dokuwiki 页面中的所有内部链接,通常是:'my_page'、'my_other_page',但不是 'http://your_page' in:

[[my_page]]

[[my_other_page|this is my other page]]

[[http://your_page|this is your page]]

【问题讨论】:

  • 试试\[\[(?!https?:\/\/)[^][|]*(?:\|[^][]*)?]],见this regex demo
  • 您可以在代码中的下一个正则表达式之后应用一个正则表达式吗?有时这比想出一个超级正则表达式更容易......
  • 谢谢,但我也需要去掉括号,我只想匹配 'my_page' 和 'my_other_page'。
  • 是的,我想过:之后应用另一个正则表达式。但第一个结果将存储在一个数组中,所以我必须对所有结果进行循环并检查它们,有点难看,但我可以做到。
  • http可以存在于分隔符之外吗?例如[[my_other_page|foo http bar]] 应该匹配my_other_page?匹配的输入是否总是以分隔符开始/结束?

标签: regex


【解决方案1】:

作为替代方案,您可以使用SKIP FAIL 方法:

\[\[https?:\/\/(*SKIP)(*FAIL)|\[\[\K[^][|]+

模式匹配:

  • \[\[https?:\/\/ 匹配 [[https:// 与可选的 s
  • (*SKIP)(*FAIL)消费你想避免的字符
  • |或者
  • \[\[\K 匹配 [[ 并忘记到目前为止匹配的内容
  • [^][|]+ 匹配除 ] [| 之外的任何字符 1+ 次

Regex demo

$strings = [
    "[[my_page]]",
    "[[my_other_page|this is my other page]]",
    "[[http://your_page|this is your page]]",
];

$re = '/\[\[https?:\/\/(*SKIP)(*FAIL)|\[\[\K[^][|]+/';

foreach ($strings as $s){
    if (preg_match($re, $s, $matches)) {
        var_dump($matches[0]);
    }    
}

输出

string(7) "my_page"
string(13) "my_other_page"

要使用| 和结束]] 验证可选部分,您可以使用否定前瞻

\[\[https?:\/\/(*SKIP)(*FAIL)|\[\[\K[^][|]+(?=(?:\|[^][]*)?]])

Regex demo

或者如果最后一部分也可以包含][

\[\[https?:\/\/(*SKIP)(*FAIL)|\[\[\K[^][|]+(?=(?:\|.*?)?]])

Regex demo

【讨论】:

    【解决方案2】:

    然后使用

    (?<=\[\[)(?!https?:\/\/)[^][|]+
    (?<=\[\[)(?!https?:\/\/)[^][|]+(?=(?:\|[^][]*)?]])
    

    regex demo

    详情

    • (?&lt;=\[\[) - 一个积极的后视,匹配紧接在 [[ 之前的位置
    • (?!https?:\/\/) - 如果当前位置右侧有 http://https://,则取消匹配的负前瞻
    • [^][|]+ - 除了][| 之外的一个或多个字符
    • (?=(?:\|[^][]*)?]]) - 一个正向的前瞻,需要在当前位置的右侧紧接以下模式序列:
      • (?:\|[^][]*)? - | 的可选出现,然后是除 [] 之外的任何零个或多个字符
      • ]] - 一个 ]] 字符串。

    注意:根据正则表达式的风格,您可能需要在字符类中转义] 或/和[ 字符,即[^][] => [^\][](JavaScript @ 987654343@) 或[^\]\[](Java、Ruby)。

    【讨论】:

      【解决方案3】:

      这是正则表达式模式,对 Wiktor Stribiżew 在评论部分的回答进行了一些调整。通过使用lookahead 和lookbehind,您可以取消选择括号。

      (?<=\[\[)(?!https?:\/\/)[^][|]*(?:\|[^][]*)?(?=]])
      

      【讨论】:

      • 几乎完美,非常感谢。它只是抓住'|这是我的另一页',我不想拥有它。目标是只包含 '[[' 之后的第一部分,而不是 '|' 之后的内容如果有的话。我不得不承认我对所有这些正则表达式都不太了解,但非常感谢
      猜你喜欢
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-27
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多