正则表达式中的前瞻非捕获组与if/then语句

6

我有一些损坏的JSON文件需要修复。

问题在于其中一个字段AcquisitionDateTime格式不正确:

{
    "AcquisitionDateTime": 2016-04-28T17:09:39.515625,
}

我想做的是将值用括号括起来。我可以很容易地使用正则表达式实现:

perl -pi -e 's/\"AcqDateTime\": (.*),/\"AcqDateTime\": \"\1\",/g' t.json

现在,我想扩展正则表达式,以便在JSON未损坏的情况下,内容不会被两次包装在""中。我面临的问题是不知道如何混合前瞻、if/then语句和捕获组。这是我的尝试:
Lookahead, if you find a ", then capture what is between it. Else capture everything.
perl -pi -e 's/\"AcqDateTime\": (?(?=\")\"(.*)\"|(.*)),/\"AcqDateTime:\" \"\1\",/g' t.json

这是我感兴趣的部分:

Lookahead for a \"  -> if yes, then capture without it. \"(.*)\" Else capture all (.*)
(?(?=\")\"(.*)\"|(.*)),

请问我哪里做错了呢?谢谢提前回答。

提示:那个\1应该是$1。而且不需要转义所有的" - ikegami
2个回答

3
一个好的开始匹配时间戳的方法是:
\S+

但这也会匹配逗号,因此我们转而使用
 [^\s,]+

现在,您也希望避免匹配引号。
 [^\s",]+

这就是你所需要的全部。

perl -i -pe's/"AcqDateTime":\s*+\K([^\s",]+)/"$1"/g' t.json

为什么不只使用 [^"]+ - Master DJon
@Master DJon,我的回答已经逐步解释了我是如何得到我所使用的内容的。你所建议的方法会匹配逗号,所以肯定行不通。或许你可以移除\s,尽管在逗号之前理论上可能存在不应包含在双引号中的空格。 - ikegami

2
以下正则表达式包含对部分引号包装(即仅在值的开头或结尾处),两端缺少包装或空值的检查:
perl -pi -e 's/\"AcqDateTime\": (|(?<!\")[^\"].*|.*[^\"](?!\")),/\"AcqDateTime\": \"\1\",/g' t.json

其中 (|(?<!\")[^\"].*|.*[^\"](?!\")) 包括:

  • 空字符串值,例如 { "AcquisitionDateTime": }
  • (?<!\")[^\"].*:不以引号开头的值,例如 { "AcquisitionDateTime": 2016" },或
  • .*[^\"](?!\"):不以引号结尾的值,例如 { "AcquisitionDateTime": "2016 }

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