【问题标题】:Regex to capture all but the last hashtag正则表达式捕获除最后一个主题标签之外的所有内容
【发布时间】:2020-07-15 05:19:48
【问题描述】:

我通常把正则表达式当作母语来使用,但今天我被这个谜题难住了。我需要捕获除最后一个主题标签之外的字符串的所有文本。除最后一个之外的任何主题标签都应包括在内,如果根本没有主题标签,它也需要匹配。

测试用例 1:

  • 输入:Foo bar #baz
  • 匹配:Foo bar

测试用例 2:

  • 输入:Foo bar #baz #qux
  • 匹配:Foo bar #baz

测试用例 3:

  • 输入:Foo bar
  • 匹配:Foo bar

由于我在 (Zapier) 中使用它的环境,我有一个严格的约束,即无论情况如何,我都需要在具有相同组号的单个捕获组中匹配字符串。 Zapier 使用 Python 引擎 FWIW。

上下文是从 Instagram 自动将照片发布到 Twitter,但需要将长度限制为 280 个字符。由于 Zapier 的 truncate 功能不允许切割干净的单词边界,因此 280 个字符可能会在主题标签的中间用完,当 Twitter 自动链接它时,可能会导致令人尴尬的结果。 (Zapier 的截断确实允许附加省略号,这可以缓解常规单词的问题。)由于包含每个主题标签并不重要,我想丢弃最后一个,以防它被截断。

【问题讨论】:

    标签: regex


    【解决方案1】:

    您可以使用展开循环方法。
    这可能是最快的方法。

    [^#]*(?:\#(?![^#]*$)[^#]*)*

    https://regex101.com/r/vlEows/1/tests

    【讨论】:

    • 这太棒了!很好很简单。
    【解决方案2】:

    就在我完成输入后,我找到了自己的解决方案(是的,橡皮鸭?它)。想我会把它发布给其他需要这个特定奇怪解决方案的人:

    ((^[^#]+$)|(?:.|\n)+)(?(2)|\s#[^#]+)
    

    测试结果:https://regex101.com/r/RNGVSL/2/tests

    更新

    来自 Wiktor Stribiżew 在 cmets 中的更简单回答:

    (?s)^(.*?)(?:\s*#[^\s#]+)?$
    

    测试结果:https://regex101.com/r/RNGVSL/3/tests

    【讨论】:

    • 永远不要使用(?:.|\n)+。将. 与适当的修饰符一起使用,(?s)(Ruby 中的m 等)。或者,如果您无权访问修饰符,请使用 [\w\W] 而不是点。交替会导致多余的回溯。
    • 另外,为什么不(?s)^(.*?)(?:\s*#[^\s#]+)?$ 并获取第 1 组的值?见regex demo
    • 我无法访问 Zapier 中的修饰符,否则我会使用 s。但是,[\w\W] 的好建议。您的简化不起作用,因为原始文本中可能需要保留换行符。为了简单起见,我只是没有在原始问题中注意到这一点。到目前为止,似乎这是赢家:((^[^#]+$)|[\w\W]+)(?(2)|\s#[^#]+).
    • 您在我回复时编辑了您的评论。立即查看您的新版本...
    • 尽管从技术上讲,根据 Regex101,与我原来的 655 步相比,2098 步的效率实际上更低。 :-)
    【解决方案3】:

    您可以匹配以下正则表达式,条件是字符串是否以井号标签结尾。

    ^(?:(?=.*#\w+$).*(?=#\w+$)|.*)
    

    Start your engine!

    如果您需要捕获组,请使用 $0,它保存完整的匹配项。

    正则表达式引擎执行以下操作。

    ^              : match beginning of string
    (?:            : begin non-capture group
      (?=.*#\w+$)  : positive lookahead asserts that the string
                     ends with a hashtag
      .*           : match 0+ characters
      (?=#\w+$)    : positive lookahead asserts that the next character
                     begins a hashtag at the end of the string
    |              : or
      .*           : match 0+ characters
    )              : end non-capture group
    

    也可以删除非捕获组并重复字符串开头的锚点:

    ^(?=.*#\w+$).*(?=#\w+$)|^.*
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 2011-07-03
      • 2011-05-20
      • 2020-12-17
      • 1970-01-01
      • 2022-12-04
      相关资源
      最近更新 更多