正则捕获组优化:忽略可选包裹标签提取类JSON文本内容
问题描述
我有一个类JSON语法的文件,需要从中提取指定行的内容。当前使用的正则表达式\s+{"\S+" "(<c(\S+)>)?(.+)"},多数情况下能把目标文本提取到第二个捕获组,但碰到目标文本被<c(...)>和</c>这类可选标签包裹时,提取结果会附带</c>(比如text7会被提取成text7</c>)。现在需要修改正则,提取出不带标签的纯净目标内容,不考虑正则的速度或简洁性。
样本文件内容:
{"title_available" "text1"} {"title_value" "<c(20a601)>text2"} {"tags" {"all" "text3"} {"ignore" "text4"} {"chargeFactor" "text5 %1%"} {"resourceSpeed" "%1% text6"} } {"rules" "bla-bla-bla\n\n \"BLA\" bla-bla-bla."} {"id1" "<c(c3baae)>text7</c>"}
期望输出:
text1 text2 text3 text4 text5 %1% %1% text6 bla-bla-bla\n\n \"BLA\" bla-bla-bla. text7
解决方案
使用以下正则表达式,提取第一个捕获组的内容即可得到纯净文本:
\s+{"\S+" "(?:<c\(\S+\)>)?(.*?)(?:<\/c>)?"}
正则说明
\s+:匹配行首的任意空白字符(空格、制表符等){"\S+" ":匹配类JSON结构里的键部分(比如{"title_available" ")(?:<c\(\S+\)>)?:非捕获组,匹配可选的开头标签<c(xxx)>,?:表示该组不参与捕获,?表示这个标签是可选的(.*?):核心捕获组(第一个捕获组),用非贪婪模式匹配中间的所有内容,避免把结尾的</c>包含进来(?:<\/c>)?:非捕获组,匹配可选的结尾标签</c>,同样不参与捕获且可选"}:匹配结构的结尾部分
测试验证
用这个正则匹配样本文件里的目标行,提取第一个捕获组的结果完全符合期望输出:
- 匹配
{"id1" "<c(c3baae)>text7</c>"}时,捕获组1得到text7,不会附带</c> - 匹配带换行和转义引号的
{"rules" "bla-bla-bla\n\n \"BLA\" bla-bla-bla."}时,能完整保留原有的特殊字符
内容的提问来源于stack exchange,提问作者Nikita Smirnov
相关产品推荐
相关产品推荐

