Json 使用jq+;猛击

Json 使用jq+;猛击,json,bash,jq,ini,Json,Bash,Jq,Ini,我正在尝试将json(对象数组)转换为ini文件: [ { "connection": { "id": "br0", "uuid": "ab1dd903-4786-4c7e-a4b4-3339b144d6c7", "stable-id": "", "type": "bridge", "interface-name": "br0", "autoconnect": "no", "autoconnect-p

我正在尝试将json(对象数组)转换为ini文件:

[
  {
    "connection": {
      "id": "br0",
      "uuid": "ab1dd903-4786-4c7e-a4b4-3339b144d6c7",
      "stable-id": "",
      "type": "bridge",
      "interface-name": "br0",
      "autoconnect": "no",
      "autoconnect-priority": "0",
      "autoconnect-retries": "-1",
      "auth-retries": "-1",
      "timestamp": "44444",
      "read-only": "no",
      "permissions": "",
      "zone": "WAN",
      "master": "",
      "slave-type": "",
      "autoconnect-slaves": "1",
      "secondaries": "",
      "gateway-ping-timeout": "0",
      "metered": "unknown",
      "lldp": "default"
    },
    "ipv4": {
      "method": "manual",
      "dns": "192.168.1.1,192.168.2.1",
      "dns-search": "",
      "dns-options": " ",
      "dns-priority": "0",
      "addresses": "192.168.1.3/24",
      "gateway": "",
      "routes": "192.168.10.0/24 192.168.1.1",
      "route-metric": "-1",
      "route-table": "0",
      "ignore-auto-routes": "no",
      "ignore-auto-dns": "no",
      "dhcp-client-id": "",
      "dhcp-timeout": "0",
      "dhcp-send-hostname": "yes",
      "dhcp-hostname": "",
      "dhcp-fqdn": "",
      "never-default": "no",
      "may-fail": "yes",
      "dad-timeout": "-1"
    }
  },
  {
    "connection": {
      ...
    },
  }
]

我想做的是:

1。将json转换为字符串

data=$(jq -r 'def keyValue:  to_entries[] | "[\(.key)]\\n\(.value | to_entries|map("\(.key)=\(.value)" ) | join("\\n") )\\n"; if type == "array" then keys[] as $k | "\(.[$k] | .connection.id)=\(.[$k] | keyValue)" elif type == "object" then "\(.connection.id)=\(. | keyValue)" else keys end' /tmp/json)
规定:

br1=[connection]\nid=br1\nuuid=ab1dd903-4786-4c7e-a4b4-3339b144d6c7\nstable-id=\ntype=fff\ninterface-name=br0\nautoconnect=no\nautoconnect-priority=0\nautoconnect-retries=-1\nauth-retries=-1\ntimestamp=1525494904\nread-only=no\npermissions=\nzone=WAN\nmaster=\nslave-type=\nautoconnect-slaves=1\nsecondaries=\ngateway-ping-timeout=0\nmetered=unknown\nlldp=default\n
br1=[802-3-ethernet]\nport=\nspeed=0\nduplex=\nauto-negotiate=no\nmac-address=\ncloned-mac-address=\ngenerate-mac-address-mask=\nmac-address-blacklist=\nmtu=1500\ns390-subchannels=\ns390-nettype=\ns390-options=\nwake-on-lan=default\nwake-on-lan-password=\n....
2。在bash中遍历字符串

while IFS="=" read -r key value; do [ "$oldkey" = "$key" ] && echo -en "$value" >> "/tmp/ini/$key" || echo -en "$value" > "/tmp/ini/$key" ; oldkey="$key"; done <<< "$data"
我快到了!但是否有可能做到更“优雅”和更高性能,避免管道、外部调用等

注意:此外,大多数情况下应该使用jq+bash完成,因为其他处理工具(如sed、awk)比我做的要慢,但我并不完全拒绝它们=)


p.S.-此转换的主要目的是编写ini文件的快速“批量操作”

将所示数组转换为“.ini”格式,只需使用以下jq程序即可完成:

def kv: to_entries[] | "\(.key)=\(.value)";

.[]
| to_entries[]
| "[\(.key)]", (.value|kv)
将其放入一个文件,比如program.jq,然后假设问题中显示的JSON(减去“…”部分)在input.JSON中,则以下调用:

jq -rf program.jq input.json
生成相应的“.ini”文件

如果要确保程序也能处理没有封闭数组的情况,可以修改上面主程序的第一行,以测试输入是否为数组,因此:

if type == "array" then .[] else . end
| to_entries[]
| "[\(.key)]", (.value|kv)

如果最终目标是生成几个.ini文件,那么我们可以重用另一个答案中定义的
def kv

def kv: to_entries[] | "\(.key)=\(.value)";
然而,驱动程序现在将是:

.[]
| [to_entries[] | "[\(.key)]", (.value|kv)]
| join("\n")
使用该程序运行jq,然后为数组中的每个项生成一个JSON字符串。使用该示例,第一个这样的字符串是:

"[connection]\nid=br0\nuuid=ab1dd903-4786-4c7e-a4b4-3339b144d6c7\nstable-id=\ntype=bridge\ninterface-name=br0\nautoconnect=no\nautoconnect-priority=0\nautoconnect-retries=-1\nauth-retries=-1\ntimestamp=44444\nread-only=no\npermissions=\nzone=WAN\nmaster=\nslave-type=\nautoconnect-slaves=1\nsecondaries=\ngateway-ping-timeout=0\nmetered=unknown\nlldp=default\n[ipv4]\nmethod=manual\ndns=192.168.1.1,192.168.2.1\ndns-search=\ndns-options= \ndns-priority=0\naddresses=192.168.1.3/24\ngateway=\nroutes=192.168.10.0/24 192.168.1.1\nroute-metric=-1\nroute-table=0\nignore-auto-routes=no\nignore-auto-dns=no\ndhcp-client-id=\ndhcp-timeout=0\ndhcp-send-hostname=yes\ndhcp-hostname=\ndhcp-fqdn=\nnever-default=no\nmay-fail=yes\ndad-timeout=-1"

然后,您可以迭代这些以换行符分隔的字符串。

仅对一个文件可以!我不想在bash中多次迭代或调用jq。我需要这样的字符串:
br1=[connection]\nid=br1\nuuid=\n……
br2=[connection]\nid=br2\nuuid=\n……
等等。在这之后,我可以使用
同时阅读
和分别编写文件。请看新的答案。太简单了!太棒了!非常感谢。
.[]
| [to_entries[] | "[\(.key)]", (.value|kv)]
| join("\n")
"[connection]\nid=br0\nuuid=ab1dd903-4786-4c7e-a4b4-3339b144d6c7\nstable-id=\ntype=bridge\ninterface-name=br0\nautoconnect=no\nautoconnect-priority=0\nautoconnect-retries=-1\nauth-retries=-1\ntimestamp=44444\nread-only=no\npermissions=\nzone=WAN\nmaster=\nslave-type=\nautoconnect-slaves=1\nsecondaries=\ngateway-ping-timeout=0\nmetered=unknown\nlldp=default\n[ipv4]\nmethod=manual\ndns=192.168.1.1,192.168.2.1\ndns-search=\ndns-options= \ndns-priority=0\naddresses=192.168.1.3/24\ngateway=\nroutes=192.168.10.0/24 192.168.1.1\nroute-metric=-1\nroute-table=0\nignore-auto-routes=no\nignore-auto-dns=no\ndhcp-client-id=\ndhcp-timeout=0\ndhcp-send-hostname=yes\ndhcp-hostname=\ndhcp-fqdn=\nnever-default=no\nmay-fail=yes\ndad-timeout=-1"