给定以下json字符串:{"key":"val"ue","other":"invalid ""quo"te"}

我想捕获值中的每个非法双引号.在该示例中,Key属性的值中有一个双引号,而名为Other的属性中有三个双引号.

我看到了许多 comments ,指出这是无效的json(正确),并且提供的json在接收之前应该是有效的.然而,在我的情况下,这是不可能的.

假设这只会出现在值中,而不会出现在键中,我认为可以安全地假设开始序列将是一个冒号后跟一个双引号. 结束序列将是一个双引号,后跟逗号或右大括号.

我try 了以下正则表达式(在许多其他版本中),它是最接近的,因此是我想要的解决方案:

/:\s?".*?(").*?[,}]/i

这正确地捕获了Key属性中的一个双引号,但只捕获了‘Other’属性中的第一个双引号. 我希望它捕获其他两个双引号以及一个单独的捕获.

我试过的另一个正则表达式:/:\s?".*?("{1,})[^,}].*?[,}]/i 这与第一个正则表达式的作用相同,但在一次捕获中捕获了两个双引号(不可取)

我的最终目标是分别捕获每个双引号,所以有四个捕获.我认为,要做到这一点,我需要的是一种让被捕者变得"贪婪"的方法.这样它就不会止步于第一个双引号.

我怎么才能做到这一点呢?

我正在使用以下PHP代码测试Regex:

$text = '{"key":"val"ue","other":"invalid ""quo"te"}';
$pattern = '/:\s?".*?(").*?[,}]/i';
preg_match_all($pattern, $text, $matches, PREG_OFFSET_CAPTURE);
echo '<pre>' . print_r($matches, true) . '</pre>';

推荐答案

您可以做的是使用The Trick...的变体

诀窍是我们match what we don't wantleft side的交替(|),然后我们capture what we do wantright side.

PCRE的好处是,左侧有verbs个可用球,而只有skip个.

(?:(?:"\s*[:,]|\{)\s*"|\\"|"\s*[:}])(*SKIP)(*F)|"

See this demo at regex101

(*SKIP)(*F)的左侧,交替使用所有"正确的"引号get matched (regex(*SKIP)(*F))skipped.任何剩余的引号都是分别位于右侧|"matched.

最后,你可以用PREG_OFFSET_CAPTURE来计算每个"非法引用"的位置.

Php相关问答推荐

如何在Laravel Controller中存储文本区域值?

如何优化-PHP 7.3.14+Laravel 6

使用PHP和WebSockets或SSE实现实时通知

根据在WooCommerce购物车和 checkout 中 Select 的送货方式显示快捷代码内容

WooCommerce数量减号和加号图标未显示

允许在WooCommerce管理员优惠券列表中显示自定义优惠券类型

获取并判断WooCommerce用户订阅结束日期

PHP-带POST验证的for循环

当配置的URL为空时禁用Laravel Slack日志(log)记录

筛选器具有多个查询之一

使用php ZipArhive类将Zip压缩文件分成多个部分

是否使用联系人表单7 wpcf7_Feedback_Response输出答复中的html?

如何用Ubuntu 22.04在VSCode中启用XDebug

HTTPPost请求在从php脚本调用时返回404,但在从node.js脚本调用时有效.终结点有效

execute_query 和prepare+execute 有什么区别?

Wordpress,配置一周第一天选项

为什么 debug_backtrace() 不返回任何内容?

在WooCommerce单产品页面中显示特价产品的节省金额

升级到 PHP 8.2:ksort 和 krsort 更改

为什么 PDO 允许使用带命名占位符的索引数组,但仅在禁用仿真时才允许?