regex - 如何使用 sed、awk 或其他 OS X 工具替换文件(JSON 格式)中的多行 block ?

标签 regex awk sed osx-yosemite

我正在寻找一个在终端中执行的单行代码,以用文本文件中我自己的上下文替换多行文本 block 。我使用的是 OSX(不是 GNU sed),无法安装任何附加工具。

我想做的是替换

{
    "user" :
    {
        "name": "Andreas",
        "age": 34
    },
    "viewer" :
    {
        "name": "Pedro",
        "age": 41
    }
}

“用户” block 内大括号之间的两行具有自己的值以获得结果:

{
    "user" :
    {
        "name": "Mike",
        "age": 29
    },
    "viewer" :
    {
        "name": "Pedro",
        "age": 41
    }
}

简单地搜索包含“name”或“age”的行是行不通的,因为它们可能属于另一个结构并且不应被修改。

通过组合几个示例,我发现这个示例可以正常工作:

sed -i '' -n $'1h;1! H;$ {;g;s#"用户"[^{]*[^}]*#"用户":\\\n\\\t{\\\n\\\t\\\t"名称": "Mike",\\\n\\\t\\\t"age": 29\\\n\\\t#p;}' config.json

但是它似乎相当复杂,这是我的问题。

  1. 如何修改匹配模式以仅检测括号之间的内容,这样我就不必重新创建“user”键。
  2. 还有其他更优雅的解决方案吗?欢迎使用 sed、awk 或 OS X 中包含的任何其他系统工具。

最佳答案

解析 JSON 并不是一个好主意(您应该看看 jq),但 awk 可以提供帮助。

例如,您可以检查 user 何时出现,然后对后续行进行操作:

awk '/user/ {f=NR}
     NR==f+2 {sub ("Andreas","Mike")}
     NR==f+3 {sub (34, 29)}
     1' file

您还可以提供新值作为参数。

如果不知道参数的值,可以使用正则表达式来匹配里面的内容:

awk '/user/ {f=NR} NR==f+2 {sub (/: ".*,$/,": \"Mike\",")} NR==f+3 {sub (/: [0-9]+$/, ": 29,")} 1' a

测试

$ awk '/user/ {f=NR} NR==f+2 {sub ("Andreas","Mike")} NR==f+3 {sub (34, 29)} 1' a
{
    "user" :
    {
        "name": "Mike",
        "age": 29
    },
    "viewer" :
    {
        "name": "Pedro",
        "age": 41
    }
}

关于regex - 如何使用 sed、awk 或其他 OS X 工具替换文件(JSON 格式)中的多行 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31876993/

相关文章:

bash - 如何将 csv 文件中的最后一列交换为第一列? + awk

正则表达式检测一行是否不以分号结尾

awk - awk FIELDWIDTHS 如何工作

perl - 每三次出现的字符串加倍

awk - 在 awk 中编写脚本

bash - 从 XML 文件中删除特定的重复行

java - 存储带有未知字符的字符串

正则表达式匹配 n 引号字符串

C++ regex_replace 问题

linux - 用变量中包含空格的sed替换文本