【发布时间】:2017-07-28 16:57:52
【问题描述】:
我正在寻找一种简单的 UNIX 方法,用于将使用 shell 脚本获得的数据保存到 YAML 文件中,例如,我想使用 shell 管道将系统中已安装包(rpms、pypi)的列表保存在单个 YAML 文件中,类似:
rpm -qa |排序 | some-yaml-tool manifest.yaml system.packages
预期结果将是一个manifest.yaml 文件,如下所示:
system:
packages:
- xz-5.2.2-2.fc24.x86_64
- xz-devel-5.2.2-2.fc24.x86_64
虽然我更喜欢 YAML,但我不会拒绝兼容 JSON 的解决方案。我真的很想找到一种方法来使用大多数发行版上可用的工具来做到这一点,而不是需要手动安装或从非官方 yum/deb 存储库安装的深奥。
如果工具很智能,它应该能够在文件和内部路径存在时创建它。
请注意,我必须从列表中删除 jq 工具,因为它确实是 not allow in-place editing。
【问题讨论】:
-
jq <filename | sponge filename可以很好地进行就地编辑——而tempfile=$(mktemp -t "$in.XXXXXX"); jq <"$in" >"$tempfile" && mv "$tempfile" "in"几乎可以移植到人们可能关心的任何地方。鉴于sed -i不能在 GNU 和 BSD 调用之间移植,因此无论如何都要使用替代公式。 -
jq显然不是一个选项,因为在尝试在包装器中实现缺失的行为时可能会出错的事情太多。是否很容易以损坏的文件告终。性能也是另一个问题,我不想为每个处理的行创建临时文件。 -
谁说您需要为每条处理线创建一个实例?编写 jq 代码来读取输入流并根据该流中的多个对或元素修改传递的内容是微不足道的。
-
为每次调用创建一个临时文件是
sed -i(以及几乎所有其他就地编辑实例)在幕后所做的。通过代表您的单独工具而不是您自己的代码创建临时临时文件,您并没有减少临时临时文件的数量。 -
请记住,在底层系统调用接口级别对就地编辑的支持极为有限(就地修改的内容需要在操作之前和之后具有相同的长度,除非您'重新追加或截断),因此如果您希望
sed -i或类似工具不创建临时文件,您希望它在内存中缓冲未知数量的内容(和在编辑进行期间内容不完整且一致,从而冒着您数据完整性的风险)。对于需要支持大于 RAM 的文件的工具来说,这是不可行的。