有一个包含内容的文件
{
"first_name": "John",
"last_name": "Smith",
"is_alive": true,
"age": 27,
"address": {
"street_address": "21 2nd Street",
"city": "New York",
"state": "NY",
"postal_code": "10021-3100"
},
"phone_numbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [
"Catherine",
"Thomas",
"Trevor"
],
"spouse": null
}
如何使用 Busybox 实用程序将内容添加到文件最后一个 } 字符之前,以使文件内容如下所示?
{
"first_name": "John",
"last_name": "Smith",
"is_alive": true,
"age": 27,
"address": {
"street_address": "21 2nd Street",
"city": "New York",
"state": "NY",
"postal_code": "10021-3100"
},
"phone_numbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [
"Catherine",
"Thomas",
"Trevor"
],
"spouse": null,
"field1": "value1",
"field2": "value2",
"field3": "value3",
"field4": "value4"
}
但是,} 字符不一定是文件中的最后一个字符,也不一定位于最后一行。
到目前为止我只找到了这个解决方案
tac file2 | sed '0,/}/s/}/}\n"field4": "value4"\n"field3": "value3",\n"field2": "value2",\n"field1": "value1",\n,/' | tac>tmp_file && mv tmp_file file2
使用该
ed
实用程序(在BusyBox
容器中测试):输出文件通过jq测试。
如果最后一个 } 是最后一行,则可以使用 head 命令来完成。在添加的文本中包含最后一个 }:
而你想要的是:
您从添加的文本中省略最后一个 } ,而是将上面的输出通过管道传输到此 sed:
使用任何 awk 和任何类似 bourne 的 shell:
请注意,它将新块的缩进设置为紧邻其之前的行的缩进,因此您不必对该缩进进行硬编码,即使后面有注释行或空白行,它也能工作。最后
}
一行。如果您非常确信文件以以下结尾
}\n
(或者}
文件末尾没有换行符),则可以使用truncate
最后 2 个字节(或 1 个字节)。事先用于tail -c
验证。之后
truncate
,文件将丢失最后一个}
,但在其他方面完好无损。此时只需>>
附加新文本(包括}
您截断的文本)。不幸的是,busybox
truncate
不理解相对大小 (-2
),因此您需要自己进行数学计算并使用它stat -c %s
来确定以字节为单位的大小。此方法也适用于非常大的文件,无需先读取所有内容。
awk
、ed
、head -n
等都读取整个文件。注意:此答案并不限于仅使用 Busybox 多二进制文件中内置的实用程序,而是使用实用程序
jq
。这个众所周知的 JSON 处理工具可作为大多数常见架构的静态二进制文件使用,无需升级安装或使用权限。您还可以通过公共 Docker 映像使用它。由于 Busybox 多二进制文件可能包含数量差异很大的内置实用程序,具体取决于所使用的 Busybox(Alpine Linux 上有 302 个实用程序,但公共 Busybox Docker 映像中额外有 100 个实用程序),并且因为这不是问题中提到,我假设该限制纯粹是人为的,并不是非常重要。
安装后,
jq
您可以通过不同的方式使用它来添加数据,具体取决于您提供新数据的形式。假设有单独的键和未编码的字符串,您将使用
jq
with--arg key value
对每个字符串进行编码并创建内部jq
变量。对于已经适当编码的值(数字、布尔值、JSON 字符串或 JSON 片段),请--argjson
使用--arg
.$
然后,您可以使用表达式内以($key1
、等)开头的键名称来访问各个数据片段,或者您可以使用特殊对象访问所有此类变量$var2
:$lastname
jq
$ARGS.named
对于 中的第一个示例文档
file.json
,这将产生以下内容:.
显然,您可以通过指定与上面表达式不同的路径来决定将数据插入到文档中的位置。例如,要将数据添加到表示至少有一个以“212”开头的家庭电话号码的人的任何输入对象: