【问题标题】:Output only values that do not contain HTML tags in parentheses from PHP array仅输出 PHP 数组中括号中不包含 HTML 标记的值
【发布时间】:2017-07-02 05:14:30
【问题描述】:

这是一个很好地解释了我的问题的示例 PHP 数组

$array = array('1' => 'Cookie Monster (<i>eats cookies</i>)',
               '2' => 'Tiger (eats meat)',
               '3' => 'Muzzy (eats <u>clocks</u>)',
               '4' => 'Cow (eats grass)');

我只需要从这个数组中返回不包含任何用括号括起来的标签的值:

- Tiger (eats meat)
- Cow (eats grass)

为此,我将使用以下代码:

$array_no_tags = preg_grep("/[A-Za-z]\s\(^((?!<(.*?)(\h*).*?>(.*?)<\/\1>).)*$\)/", $array);
foreach ($array_no_tags as $a_n_t) {echo "- ".$a_n_t."<br />";}

假设[A-Za-z]可能是\s是一个空格\(左括号,@987654329 @是标签拒绝语句的开始&lt;(.*?)(\h*).*?&gt;(.*?)&lt;\/\1&gt;标签本身,).)*$是标签拒绝语句的结束,@ 987654332@ 是右括号

没有任何作用。

print_r($array_no_tags); 返回空数组。

【问题讨论】:

  • 我认为 strip_tags 会为你工作。 php.net/manual/en/function.strip-tags.php
  • 如何使用前瞻:/^(?!.*?\([^)&lt;]*&lt;\w)/
  • @bobble bubble,您的回复非常有效,您能否将其重新发布为答案以便我投票?
  • 很高兴它也有帮助(:我也提出了答案(我认为乔希的答案已经很准确了)。
  • 实际上 Josh 的不适合我今天遇到的另一个案例,同时你的例子完美匹配。反之亦然。虽然这两种情况对我来说看起来相似,但我仍然没有认识到隐藏的差异。所以你也为我节省了很多时间和精力,谢谢

标签: php arrays regex


【解决方案1】:

你的模式看起来有点过于复杂。我认为在负前瞻中可能有一个简单的模式来检查 ( ) 内没有任何 &lt;x 可能就足够了。

$array_no_tags = preg_grep("/^(?!.*?\([^)<]*<\w)/", $array);

PHP demo at eval.in

所以not match (?! if 有一个( 左括号,然后是[^)&lt;]* 任意数量的characters that are not )&lt;,然后是&lt;\w 较小的符号,然后是@987654324 @。

请记住,有很好的regex tools like regex101 可用于测试模式。

【讨论】:

  • > 你的模式看起来有点过于复杂......当一个人试图从不同的来源编译一个表达式时会发生这种情况,而他几乎不理解他在屏幕上看到的内容)
  • @user3354912 我记得大约 15 年前我开始使用正则表达式时,这对我来说是多么令人困惑,但我很快就喜欢上了它。我将link to regex101 与答案放在一起。右上角有一个解释窗口,解释了模式的每一个细节。
  • @user3354912 顺便提一下:如果您的元素包含换行符,请使用 dotall flag 使点也匹配换行符:/^(?!.*?\([^)&lt;]*&lt;\w)/s
【解决方案2】:

您可以使用以下表达式来匹配括号内带有 HTML 标记的字符串:

/\([^)]*<(\w+)>[^<>]*<\/\\1>[^)]*\)/

然后将PREG_GREP_INVERT flag 设置为true,以便仅返回不匹配的项目。

$array_no_tags = preg_grep("/\([^)]*<(\w+)>[^<>]*<\/\\1>[^)]*\)/", $array, true);

说明:

  • \( - 匹配文字 ( 字符
    • [^)]* - 否定字符类以匹配零个或多个非) 字符
    • &lt;(\w+)&gt; - 捕获与开始元素的标签名称匹配的第一组
    • [^&lt;&gt;]* - 否定字符类以匹配零个或多个非&lt;&gt; 字符
    • &lt;\/\1&gt; - 对捕获组一的反向引用以匹配结束标记
    • [^)]* - 否定字符类以匹配零个或多个非) 字符
  • \) - 匹配文字 ) 字符

如果您不关心元素标签周围的括号,那么您也可以使用以下简化表达式:

/<(\w+)>[^<>]+<\/\\1>/

同样,你会使用:

$array_no_tags = preg_grep("/<(\w+)>[^<>]+<\/\\1>/", $array, true);

【讨论】:

  • 其实你之前的回答也是可行的。有什么区别? (我会保留在这个答案中,以防万一)$array_no_tags = preg_grep("/&lt;(\w+)&gt;[^&lt;&gt;]+&lt;\/\\1&gt;/", $array, true);
  • @user3354912 - 是的,那个有效,但是当我重新阅读这个问题时,我意识到我没有检查括号,所以我更新了它。
  • 另外非常感谢的解释。逐渐开始对自己进行正则表达式就足够了。 :)
  • @user3354912 - 如果您刚开始使用正则表达式,我强烈建议您查看 regex101.com,这是我在测试答案时使用的the example。它非常有用,因为它会在您打字时为您提供反馈。我基本上就是这样学习的。
  • 这实际上是我第一次面临使用正则表达式的必要性。它们看起来很吓人,但实际上并非如此,尤其是当有人费心解释时)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 2018-02-22
相关资源
最近更新 更多