使用sed查找引号内部并跳过转义引号

时间:2014-06-17 03:45:19

标签: regex bash sed

我有一个curl调用查询JIRA REST API并返回如下所示的JSON字符串(期望在一行上):

 {
    "expand":"renderedFields,names,schema,transitions,operations,editmeta,changelog",
    "id":"36112","self":"https://jira.company.com/rest/api/2/issue/36112",
    "key":"FOO-1218",
    "fields":
        {"summary":"the \"special\" field is not returning what is expected"}
 }

我试图解析"摘要"使用此sed脚本的字段:

sed 's/^.*summary":"\([^"]*\)".*$/\1/'

如果"摘要"没有逃脱\"在它内部 - 但当然,对于逃脱的报价,我从这个例子中得到的是:

the \

我想要的输出是:

the \"special\" field is not returning what is expected

或者甚至更喜欢这个:

the "special" field is not returning what is expected

我不能在sed中做一个lookbehind,是否有一种简单的方法可以在bash脚本中解决这个问题?

4 个答案:

答案 0 :(得分:2)

您要求使用sed编写的JSON解析器。对不起,但这太疯狂了。

这是一个在python中做到这一点的理智方式的例子:

import requests
response = requests.get(JIRA_API_ENDPOINT, headers = JIRA_HEADERS)
obj = response.json()
obj['fields']['summary']

在python中还有一个很好的JIRA API包装器,名为jira-python。只需使用它,您就不必进行任何解析。我以前用它效果很好。点击此处:http://jira-python.readthedocs.org/en/latest/

你的同事会感谢你。

答案 1 :(得分:1)

对于双引号的内部,你真的想要至少其中一个设施:

  1. lookarounds(因此您可以检查引用前面和后面的内容)。
  2. \K(所以你可以删除开头的报价)
  3. 检查捕获组的能力(因此您可以匹配整个报价,但只捕获内部的内容)。
  4. 通常,你会想要这样的东西:

    (?<=(?<!\\)")(?:\\"|[^"])*(?=")
    

    在使用grep -P的{​​{1}}模式下,您可以使用更多功能,例如我将在此处添加的占有量词:

    PCRE

    请注意,(?<=(?<!\\)")(?:\\"|[^"])*+(?=") 通常可以跨多行运行,您通常使用[^"]进行控制,但[^"\r\n]只能逐行查看。

答案 2 :(得分:0)

对于这种有限的情况,您可以使用类似

的内容
vnix$ sed -n 's/.*summary":"\(\([^\\"]*\|\\.\)*\)".*/\1/p' file.json
the \"special\" field is not returning what is expected

在引用的字符串中,不允许使用双引号,除了在文字反斜杠后立即允许任何字符。字符类也不允许使用反斜杠,以防止出现反斜杠&#34;泄漏&#34;进入错误的部分匹配。字符类之后的重复只是一个优化,以避免不必要的回溯。

任何将此概括的尝试都会很快变得非常笨拙。 Friedl book有一个例子,它超过了一页,只是为了说明这是徒劳的。

答案 3 :(得分:0)

经过严重的挣扎,我找到了一种适用于这个非常具体的用例的方法。我将转义的引号(\&#34;)转换为五个下划线( _ )的更加模糊的字符序列,执行正则表达式,然后将其转换回来:

sed -e 's/\\"/_____/g' -e 's/^.*summary":"\([^"]*\)".*$/\1/' -e 's/_____/"/g'

所以完整的测试看起来像这样:

echo '{"expand":"renderedFields,names,schema,transitions,operations,editmeta,changelo‌​g","id":"36112","self":"https://jira.company.com/rest/api/2/issue/36112","key":"F‌​OO-1218","fields":{"summary":"the \"special\" field is not returning what is expected"}}' | sed -e 's/\\"/_____/g' -e 's/^.*summary":"\([^"]*\)".*$/\1/' -e 's/_____/"/g'

输出如下:

the "special" field is not returning what is expected