使用PHP查找单引号和双引号之间的内容

4
My text "can contain" both single 'and double"' quotes. The quotes "can also be 'nested" as you can see.

期望结果

(包含3个元素的数组)

can contain
and double"
can also be 'nested

我已经走了多远

虽然我不是正则表达式专家,但我仍然成功地获取了双引号之间的文本,例如我可以“获取这个”文本

preg_match_all("~\"(.*?)\"~", $text, $between);
print_r($between);

有效/无效

  • 有效: This is "A text" (A text)
  • 有效: This is 'A text' (A text)
  • 有效: This is "A 'text" (A 'text)
  • 有效: This is 'A "text' (A "text)
  • 无效: This is "A text (引号不匹配 1)
  • 无效: This is 'A text (引号不匹配 1)
  • 无效: This is "A "text" (引号不匹配 3)
  • 无效: This is 'A 'text'(引号不匹配 3)
  • 无效: This "is ' A " text' (交叉引号)

其他说明

  • 如果出现错误,例如未关闭的引号,则可以中断 (This "has "one wrong" quote)
  • 我更喜欢使用正则表达式解决方案,但是如果有更好的非正则表达式解决方案也可以。

我的想法

我的猜测是需要循环检查每个字符。如果以"开头,则需要将字符步进到下一个"以进行包装。然后,我猜需要从该位置重新开始,以查看下一个引号类型并再次执行此操作,直到字符串结束。

在Stackoverflow上不起作用的答案

此答案对我的问题无效:regex match text in either single or double quote

可以在此处查看证明:https://regex101.com/r/OVdomu/65/


@NigelRen 没有,我更新了他的演示,并且它几乎包含了字符串的所有内容,所以它的工作方式与我所希望的不同。https://regex101.com/r/OVdomu/65/ - Jens Törnell
@WiktorStribiżew 我在这里测试了你的正则表达式:https://regex101.com/r/WSaYeh/1/。我很惊讶它的工作效果如此出色。我试图使其崩溃,但是无法做到。你看到任何潜在问题吗? - Jens Törnell
preg_match_all('~(?|"([^"]*)"|\'([^\']*)\')~', $txt, $matches); print_r($matches[1]); 在遇到无效(不对称引号)的情况下会中断。 - Wiktor Stribiżew
@Yoshi,非常好的观点,因为我在我的问题中没有涵盖到那种情况。在我的情况下,它应该被视为无效,并像Wiktor的答案一样工作(将“B' C”作为第一部分,然后中断或跳过)。 - Jens Törnell
1
@JensTörnell 或许 这个答案 也会有所帮助(演示)。它还可以处理转义引号。 - bobble bubble
显示剩余2条评论
1个回答

1

你可以使用

if (preg_match_all('~(?|"([^"]*)"|\'([^\']*)\')~', $txt, $matches)) { 
    print_r($matches[1]);
}

查看正则表达式演示PHP演示

还有一种支持转义引号的变体:

'~(?|"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')~s'

请查看this regex demo

(?|"([^"]*)"|\'([^\']*)\')是一个分支重置组, 匹配的是",然后是除了"之外的任意0个或多个字符,然后是",或者是',然后是除了'之外的任意0个或多个字符,然后是'。同时,将匹配引号之间的所有内容捕获到第1组中。


我使用第一个。据我所知,它适用于我所有的情况,并且更短。变体看起来更像是一种黑客技巧而不是正则表达式。但是有备选方案总是好的,特别是对于未来访问这个问题的其他人来说。 - Jens Törnell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接