我想用sed来匹配由分隔的行的块模式1 /模式2,然后执行操作仅在包含块(例如打印块)pattern3.
在下面的示例中,我正在寻找" 抓住我,如果可以的话 ",在由匹配{和}的行分隔的所有块中(然后我想完整地打印匹配的块).
我尝试过的:
sed -n -e '/{/,/}/{1h;1!{$!{H;d};H;x;/catch me if you can/p}}'
Run Code Online (Sandbox Code Playgroud)
(想法是匹配由{和}分隔的块,然后将每个块累积到保留空间;在每个块的末尾,交换保持空间并执行匹配以" 抓住我,如果可以的话 ").这不起作用,因为所有匹配的块一起被sed视为单个块,而不是单独处理每个块.
输入数据:
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block2": {
"bbb": "24680",
"bar": "blah",
"foo": "argh",
"ccc": "135"
},
"block3": {
"ddd": "zzz"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
Run Code Online (Sandbox Code Playgroud)
期望的输出:
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can"
},
Run Code Online (Sandbox Code Playgroud)
注1:每个块内的字段顺序是随机的.字段数和值的长度在块之间不是恒定的.我正在寻找的字段可能在某些块中丢失(而不是仅具有不同的值).
注2:出于教育目的,我更喜欢使用sed的解决方案,但如果不可能,awk或bash也可以.请不要使用perl或其他工具.
参考文献:
我就是这样做的.这里有两个版本,一个用于BSD(Mac OS X)sed(也适用于其他不运行GNU的系统sed),另一个用于GNU sed.
sed$ cat script.bsd-sed
/{/,/}/{
/{/{ h; b next
}
/}/{ H; x; /catch me if you can/p; b next
}
H
:next
}
$ sed -n -f script.bsd-sed data
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
$
Run Code Online (Sandbox Code Playgroud)
逻辑是:
-n).{和的行之间}{,则将该模式复制到保留空间并跳转到标签next.},则将其添加到保留空间; 切换模式并保持空间; 如果图案空间(先前保持空间)与您的其他图案匹配(如果可以,请抓住我),打印它; 跳到标签next.BSD(经典)之后sed不需要任何内容b next,因此}动作在下一行.
sed$ cat script.gnu-sed
/{/,/}/{
/{/{ h; b next }
/}/{ H; x; /catch me if you can/p; b next }
H
:next
}
$ /opt/gnu/bin/sed -n -f script.gnu-sed data
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
$
Run Code Online (Sandbox Code Playgroud)
GNU sed在标签终止命令后识别分号或闭括号,因此它允许更紧凑的表示法.你甚至可以将它们整合成一行 - 你必须添加几个分号:
$ /opt/gnu/bin/sed -n -e '/{/,/}/{ /{/{ h; b next }; /}/{ H; x; /catch me if you can/p; b next }; H; :next }' data
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
$
Run Code Online (Sandbox Code Playgroud)
您也可以删除不在模式匹配中的空格:
$ /opt/gnu/bin/sed -n -e '/{/,/}/{/{/{ h;b next};/}/{H;x;/catch me if you can/p;b next};H;:next}' data
"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
$
Run Code Online (Sandbox Code Playgroud)
data"block1": {
"foo": "abcd",
"bar": "catch me if you can",
"aaa": "12345"
},
"block2": {
"bbb": "24680",
"bar": "blah",
"foo": "argh",
"ccc": "135"
},
"block3": {
"ddd": "zzz"
},
"block4": {
"foo": "xyz",
"bar": "catch me if you can",
}
"block5": [
"oops": "catch me if you can"
],
"block6": {
"rhubarb": "dandelion"
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
484 次 |
| 最近记录: |