如何在 shell 脚本中缩小 JSON?
How can I minify JSON in a shell script?
我一直在寻找一种在 bash 控制台中丑化某些 JSON 的方法。这有助于以后在另一个命令中使用它(例如,将 json 内联传递给 httpie
)
给予:
{
"foo": "lorem",
"bar": "ipsum"
}
我要获取:
{"foo":"lorem","bar":"ipsum"}
注意: 这个问题的灵感来自 it's pretty-print counterpart。但是,谷歌搜索 bash minify json 没有给我正确的结果,因此这个问题是 minify/uglify。
TL;DR: 使用 jj -u < my.json
似乎是最有效的,使用 jj 工具。
但是,如果您已经安装了 python 并且不想使用新的第三方工具来完成此类任务,python 单行代码是一种非常有效的方法:
python -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)' < my.json
性能基准
这是脚本,使用 ruby 的 benchmark-ips
:
#!/usr/bin/env ruby
# frozen_string_literal: true
require "benchmark/ips"
require "tempfile"
commands= <<~SH.split("\n")
python3 -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)'
jq --compact-output
xidel -s - -e '$json' --printed-json-format=compact
jj -u
yq eval -j -I=0
SH
def label(cmd)
"%s (%s)" % [
name = cmd.split.first,
`#{name} --version 2>&1`[/\d+(\.\d+)*/]
]
end
file = Tempfile.new('foo')
file.write <<~JSON
{
"foo": "lorem",
"bar": "ipsum"
}
JSON
file.close
at_exit { file.unlink }
Benchmark.ips do |x|
commands.each do |cmd|
x.report(label(cmd)) do
system(cmd, in: file.path, out: File::NULL) or raise label(cmd) + " failed"
end
end
x.compare!
end
我的 mac(16 GB 2133 MHz LPDDR3、1.4 GHz 四核英特尔酷睿 i5)的结果:
Warming up --------------------------------------
python3 (3.9.6) 2.000 i/100ms
jq (1.6) 3.000 i/100ms
xidel (0.9.8) 4.000 i/100ms
jj (1.2.3) 19.000 i/100ms
yq (4.11.2) 10.000 i/100ms
Calculating -------------------------------------
python3 (3.9.6) 23.024 (± 0.0%) i/s - 116.000 in 5.040842s
jq (1.6) 34.140 (± 2.9%) i/s - 171.000 in 5.011323s
xidel (0.9.8) 37.127 (±13.5%) i/s - 184.000 in 5.084564s
jj (1.2.3) 170.997 (±13.5%) i/s - 836.000 in 5.014322s
yq (4.11.2) 83.604 (±20.3%) i/s - 400.000 in 5.041262s
Comparison:
jj (1.2.3): 171.0 i/s
yq (4.11.2): 83.6 i/s - 2.05x (± 0.00) slower
xidel (0.9.8): 37.1 i/s - 4.61x (± 0.00) slower
jq (1.6): 34.1 i/s - 5.01x (± 0.00) slower
python3 (3.9.6): 23.0 i/s - 7.43x (± 0.00) slower
注意:这是漂亮的打印基准,jj也是最好的!
与xidel:
xidel -s input.json -e '$json' --printed-json-format=compact
#or
xidel -s input.json -e 'serialize-json($json)'
{"foo": "lorem", "bar": "ipsum"}
有趣的“基准”,Ulysse BN。
我无法测试 jj
,但在我的旧 cpu 上,这些是我的结果:
var='{
"foo": "lorem",
"bar": "ipsum"
}'
time (for i in {1..100}; do python -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)' <<< "$var" >& /dev/null; done)
real 0m10.813s
user 0m7.532s
sys 0m5.798s
time (for i in {1..100}; do jq --compact-output <<< "$var" >& /dev/null; done)
real 0m10.500s
user 0m1.835s
sys 0m0.769s
time (for i in {1..100}; do xidel -se '$json' --printed-json-format=compact <<< "$var" >& /dev/null; done)
real 0m2.250s
user 0m1.692s
sys 0m0.889s
您可以使用 jq -c
(紧凑)选项。
jq -c . < input.json
yq
通过使用输入文件(包含美化的 JSON)为我工作
yq eval -j -I=0 uglify-test.txt
文档 link:https://mikefarah.gitbook.io/yq/usage/convert
jq-minify
这是一个 bash 脚本,它将写回缩小后的文件
works with bash v3.2+ and jq v1.6+
#!/usr/bin/env bash
set -eu
path=
options=()
# change -c to -r to get pretty-print
set -- "$@" -c .
for arg; do
if [ -f "$arg" ]; then
if [ -n "$path" ]; then
echo "Cannot specify multiple paths to jq-minify" >&2
exit 1
fi
path="$arg"
else
options+=("$arg")
fi
done
tmp=$(mktemp)
jq "${options[@]}" "$path" >"$tmp"
cat "$tmp" >"$path"
我一直在寻找一种在 bash 控制台中丑化某些 JSON 的方法。这有助于以后在另一个命令中使用它(例如,将 json 内联传递给 httpie
)
给予:
{
"foo": "lorem",
"bar": "ipsum"
}
我要获取:
{"foo":"lorem","bar":"ipsum"}
注意: 这个问题的灵感来自 it's pretty-print counterpart。但是,谷歌搜索 bash minify json 没有给我正确的结果,因此这个问题是 minify/uglify。
TL;DR: 使用 jj -u < my.json
似乎是最有效的,使用 jj 工具。
但是,如果您已经安装了 python 并且不想使用新的第三方工具来完成此类任务,python 单行代码是一种非常有效的方法:
python -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)' < my.json
性能基准
这是脚本,使用 ruby 的 benchmark-ips
:
#!/usr/bin/env ruby
# frozen_string_literal: true
require "benchmark/ips"
require "tempfile"
commands= <<~SH.split("\n")
python3 -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)'
jq --compact-output
xidel -s - -e '$json' --printed-json-format=compact
jj -u
yq eval -j -I=0
SH
def label(cmd)
"%s (%s)" % [
name = cmd.split.first,
`#{name} --version 2>&1`[/\d+(\.\d+)*/]
]
end
file = Tempfile.new('foo')
file.write <<~JSON
{
"foo": "lorem",
"bar": "ipsum"
}
JSON
file.close
at_exit { file.unlink }
Benchmark.ips do |x|
commands.each do |cmd|
x.report(label(cmd)) do
system(cmd, in: file.path, out: File::NULL) or raise label(cmd) + " failed"
end
end
x.compare!
end
我的 mac(16 GB 2133 MHz LPDDR3、1.4 GHz 四核英特尔酷睿 i5)的结果:
Warming up --------------------------------------
python3 (3.9.6) 2.000 i/100ms
jq (1.6) 3.000 i/100ms
xidel (0.9.8) 4.000 i/100ms
jj (1.2.3) 19.000 i/100ms
yq (4.11.2) 10.000 i/100ms
Calculating -------------------------------------
python3 (3.9.6) 23.024 (± 0.0%) i/s - 116.000 in 5.040842s
jq (1.6) 34.140 (± 2.9%) i/s - 171.000 in 5.011323s
xidel (0.9.8) 37.127 (±13.5%) i/s - 184.000 in 5.084564s
jj (1.2.3) 170.997 (±13.5%) i/s - 836.000 in 5.014322s
yq (4.11.2) 83.604 (±20.3%) i/s - 400.000 in 5.041262s
Comparison:
jj (1.2.3): 171.0 i/s
yq (4.11.2): 83.6 i/s - 2.05x (± 0.00) slower
xidel (0.9.8): 37.1 i/s - 4.61x (± 0.00) slower
jq (1.6): 34.1 i/s - 5.01x (± 0.00) slower
python3 (3.9.6): 23.0 i/s - 7.43x (± 0.00) slower
注意:这是漂亮的打印基准,jj也是最好的!
与xidel:
xidel -s input.json -e '$json' --printed-json-format=compact
#or
xidel -s input.json -e 'serialize-json($json)'
{"foo": "lorem", "bar": "ipsum"}
有趣的“基准”,Ulysse BN。
我无法测试 jj
,但在我的旧 cpu 上,这些是我的结果:
var='{
"foo": "lorem",
"bar": "ipsum"
}'
time (for i in {1..100}; do python -c 'import json, sys;json.dump(json.load(sys.stdin), sys.stdout)' <<< "$var" >& /dev/null; done)
real 0m10.813s
user 0m7.532s
sys 0m5.798s
time (for i in {1..100}; do jq --compact-output <<< "$var" >& /dev/null; done)
real 0m10.500s
user 0m1.835s
sys 0m0.769s
time (for i in {1..100}; do xidel -se '$json' --printed-json-format=compact <<< "$var" >& /dev/null; done)
real 0m2.250s
user 0m1.692s
sys 0m0.889s
您可以使用 jq -c
(紧凑)选项。
jq -c . < input.json
yq
通过使用输入文件(包含美化的 JSON)为我工作
yq eval -j -I=0 uglify-test.txt
文档 link:https://mikefarah.gitbook.io/yq/usage/convert
jq-minify
这是一个 bash 脚本,它将写回缩小后的文件
works with bash v3.2+ and jq v1.6+
#!/usr/bin/env bash
set -eu
path=
options=()
# change -c to -r to get pretty-print
set -- "$@" -c .
for arg; do
if [ -f "$arg" ]; then
if [ -n "$path" ]; then
echo "Cannot specify multiple paths to jq-minify" >&2
exit 1
fi
path="$arg"
else
options+=("$arg")
fi
done
tmp=$(mktemp)
jq "${options[@]}" "$path" >"$tmp"
cat "$tmp" >"$path"