【问题标题】:Remove all but specified hashtags at the end of a string using regex使用正则表达式在字符串末尾删除所有未指定的主题标签
【发布时间】:2017-06-28 13:01:17
【问题描述】:

我有一个正则表达式,几乎可以按我的意愿工作,但我需要有关如何仅在字符串末尾删除除选定主题标签之外的所有主题标签的建议。

现在我有以下内容:

preg_replace('/(?!#hashtag|#DoNotRemoveThis)(#[\w-]+)/', '', $post_caption);

输入(去掉粗体): 字符串中间的任何#hashtag 都不应被删除,无论它是什么,例如#DoNotRemoveThis #KeepThisHashtag 和字符串末尾的任何主题标签都应该被删除,除非它与正则表达式中的异常匹配。 #deletethis #DoNotRemoveThis #thismustgoaway

想要的输出: 字符串中间的任何#hashtag 都不应被删除,无论它是什么,例如#DoNotRemoveThis #KeepThisHashtag 和字符串末尾的任何主题标签都应该被删除,除非它与正则表达式中的异常匹配。 #DoNotRemoveThis

唯一的问题是它还会删除字符串中间未指定的主题标签——我希望字符串中的所有主题标签保持完整,并删除末尾的所有主题标签(排除的主题标签除外)。

请查看现场示例以获得更好的理解:https://regex101.com/r/A0Ebor/1

【问题讨论】:

  • /(?!#hashtag|#DoNotRemoveThis)(#[\w-]+)$/ 尝试在正则表达式的末尾添加一个美元符号(表示字符串的结尾)
  • 好的,我明白了:最后是一系列标签。
  • @WiktorStribiżew 是的,我想删除#deletethis 和#thismustgoaway。其他主题标签应保持不变。
  • 在您的示例中,不应删除倒数第三个标签 (#deletethis),对吗?因为它不在字符串的末尾……那你为什么把它命名为#deletethis?请澄清

标签: php regex string preg-replace


【解决方案1】:

你可以使用

'/#(?!(?:hashtag|DoNotRemoveThis)\b)[\w-]+(?=(?:\s+#[\w-]+)*\s*$)/iu'

请参阅regex demo

详情

  • # - 一个井号
  • (?!(?:hashtag|DoNotRemoveThis)\b) - 如果有 hashtagDoNotRemoveThis 后跟单词边界,则匹配失败
  • [\w-]+ - 1 个或多个单词字符或连字符
  • (?=(?:\s+#[\w-]+)*$) - 仅在当前位置的右侧有以下内容时才返回匹配项:
    • (?:\s+#[\w-]+)* - 零个或多个序列:
      • \s+ - 1+ 个空格
      • #[\w-]+ - 哈希 + 一个或多个单词字符或连字符
    • \s* - 0+ 个空格(以防有尾随空格)
    • $ - 字符串结尾(可以用换行符继续,如果不是预期的,请替换为\z

末尾的/i 将使模式不区分大小写。

我假设 hastags 以单词 char 结尾,因此,\b。如果您想匹配除以hashtagDoNotRemoveThis 开头的标签以外的任何标签,请删除

uUNICODE 修饰符使正则表达式能够很好地处理输入字符串中的所有 Unicode 字母和数字,并且还使 \w 能够识别 Unicode(它将匹配所有 Unicode 字母、数字和 _ 字符)。

如果我们要谈论优化提高模式效率,在 PCRE 中,检查hashtagDoNotRemoveThis 是有意义的之后,我们匹配#,后跟单词/连字符。但是,要使其正常工作,我们需要

  • 在 PCRE 正则表达式中将环视拆分为多个环,因此无法使用交替(这会导致后视长度未知且不支持此类后视)
  • #[\w-]+ 模式上使用原子组,即。 (?>#[\w-]+) 或所有格量词 ++(即 #[\w-]++ 禁用回溯到模式中。

因此,您可以使用 Casimir 的答案中的模式或原子组变体:

'/#(?>[\w-]+)(?<!#hashtag|#DoNotRemoveThis)(?=(?:\s+#[\w-]+)*\s*$)/ui'

another regex demo

【讨论】:

  • 这很好用——不过有一个问题:我应该在正则表达式的哪个位置放置 /i 以使其不区分大小写?
  • 查看我的更新,只需在尾随 regex delimiter / 之后添加 i 修饰符。
  • @AbrahamMurcianoBenzadon 因为hashtag|DoNotRemoveThis 包含字母。
  • 添加 u 修饰符 /iu
  • @WiktorStribiżew 谢谢,您的详细解释也非常感谢!
【解决方案2】:

你可以用这个:

~#[\w-]++(?<!#hashtag|#DoNotRemoveThis)(?=(?:\s+#[\w-]+)*+\s*$)\s*~

demo

详情:

~
#[\w-]++   # match a hashtag (and forbids backtracking using a possessive quantifier)
(?<!#hashtag|#DoNotRemoveThis) # check if the tag isn't forbidden
(?=(?:\s+#[\w-]+)*+\s*$) # check if the tag is followed by eventual other tags until the end
\s* # match an eventual trailing whitespace
~

【讨论】:

  • 这与我的模式基本相同。您可以在我的答案下方发表评论。由于模式中的后视和所有格量词,它的可移植性较差。
  • 不是真的,主要区别是这个效率高。
  • 如果您认为我的答案只是您的副本,请随时举报。
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 2010-11-23
  • 2021-11-24
  • 2013-10-30
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多