首页 > 解决方案 > sed 帮助:如何仅当在另一个匹配行范围内找到时打印一系列行

问题描述

我有一些输入,您可能会将其识别为 JSON 流,我需要通过一个简单的 shell 脚本对其进行处理

我选择使用 sed,因为我需要进行的六种其他操作已经可以很好地使用 sed。

下面是场景。

输入1:

{
    "Expr": {
        "Criteria": [
            {
               "Values": [
                    {
                        "displayValue": "MyObject",
                        "value": "UUID"
                    }
                ]
            }
        ],
        "Type": "SELECTED"
    }
} 

预期结果 1(打印包含 displayValue + 值对的子句 [s]):

            {
                "displayValue": "MyObject",
                "value": "UUID"
            }

试图:

$ sed -n -e '/"Expr":/,/"Type": "SELECTED"/ {/"Values":/,/^                    }$/ {/^                    {/,/^                    }/p;};}' /tmp/input1.json

实际结果(好):

            {
                "displayValue": "MyObject",
                "value": "UUID"
            }

这个输入2有问题:

{
    "Expr": {
        "Criteria": [
            {
               "Values": [
                    {
                        "displayValue": "MyObject",
                        "value": "UUID"
                    }
                ]
            }
        ],
        "Type": "NOT_SELECTED"
    }
}

结果出乎意料(因为外层嵌套是 NOT_SELECTED,除非 SELECTED,否则不要匹配):

$ sed -n -e '/"Expr":/,/"Type": "SELECTED"/ {/"Values":/,/^                    }$/ {/^                    {/,/^                    }/p;};}' /tmp/input2.json

结果 2:

            {
                "displayValue": "MyObject",
                "value": "UUID"
            }

是我,还是我平台上的 sed 错误?否则,您能否提出解决此问题的好方法?

约束是我不想打印不在“类型”为“已选择”范围内的“标准”行。

标签: jsonsed

解决方案


这可能对您有用(GNU sed):

sed -En '/"Expr"/{:a;n;H;/"Values"/h;/"Type"/!ba;/"SELECTED"/!d;g;s/.*\n((\s*)\{.*\2\}).*/\1/p}' file

使用循环而不是范围。

"Expr"在and之间形成一个循环,"Type"并且只有在引用的单词"SELECTED"存在时才继续。

在保持空间中执行循环保存Values,然后操作保存的内容以仅显示所需的部分。

注意这是一个过滤操作,所以使用该-n选项。


推荐阅读