
入力する
[
"8.1.1",
"7.4.33",
"7.4.5",
"8.2.6"
]
出力
{
"7": "7.4.33",
"7.4": "7.4.33",
"8": "8.2.6",
"8.1": "8.1.1",
"8.2": "8.2.6"
}
出力は次のオブジェクトです。
- キーは次のとおりです。基本存在(たとえば
8
)すると、値は次のようになります。ベストバージョンその専攻のために - キーは次のとおりです。一次、二次存在(たとえば
7.4
)すると、値は次のようになります。ベストバージョンこの専攻/不専攻の場合
数多くの試行錯誤の末、今では専攻だけを抽出して配列に減らすことができるようになりました。どんな助けでも大変感謝します!
echo "[\"8.1.1\",\"7.4.33\",\"7.4.5\",\"8.2.6\"]" | jq -n 'reduce input[] as $version ({}; .[($version | split(".")[0])] += [$version])'
任意の出力:
{
"8": [
"8.1.1",
"8.2.6"
],
"7": [
"7.4.33",
"7.4.5"
]
}
編集する:PHPを理解できる人にとっては、参照やあいまいさを避けるために同じことを行うCLIスクリプトがあります。
#!/usr/bin/env php
<?php
array_shift($argv);
usort($argv, 'version_compare');
echo json_encode(
array_reduce(
array_reverse($argv),
function (array $prev, $version) use($argv) {
[$major, $minor] = explode('.', $version, 3);
$majors = array_filter($argv, function ($v) use ($major) {
return substr($v, 0, 1) === $major;
});
$minors = array_filter($argv, function ($v) use ($major, $minor) {
return substr($v, 0, 3) === "$major.$minor";
});
return $prev + [
$major => end($majors),
"$major.$minor" => end($minors),
];
},
[]
),
JSON_FORCE_OBJECT
);
答え1
次のように見えます。
jq -c '
map(split(".") | map(tonumber)) | # transform the version number strings
# to arrays of numbers so we can
# sort them.
sort | # those arrays of numbers are sorted numerically in effect
# conveniently achieving a semver sort
map(map(tostring)) | # convert the numbers in the arrays back to
# string so we can manipulate them as such more
# easily.
map({
(.[0]) : join("."),
(.[0] + "." + .[1]) : join(".")
}) | # create a {"x":"x.y.z","x.y":"x.y.z"} object for each of
# those arrays sorted in ascending version number
add # adding those objects means merging them, with the last one
# for a given key taking precedence.
' file.json
しかし、これを行うのはjq
面白い脳回転の練習ですが、この問題を解決するには、JSONモジュール(Perl / Ruby / Pythonなど)がある一般的なプログラミング言語を使用すると、アルゴリズムとコードがはるかに簡単になる可能性があると思いました。 、理解し、進み続けなさい。たとえば、次のようになりますperl
。
perl -MJSON -MSort::Versions -l -0777 -ne '
$j = decode_json($_);
for (sort versioncmp @$j) {
@p = split/\./;
$max{$p[0]} = $_;
$max{"$p[0].$p[1]"} = $_
}
print encode_json(\%max)' file.json
(これらのJSON
モジュールSort::Versions
はシステムにデフォルトでインストールされていない可能性がありますが、ほとんどjq
インストールされません。)
または、ここには数値の合計しかないので、.
デフォルトのawkを使用して実行します(バージョンsort
ソート用のGNUとgrep
バージョン番号抽出用のGNUと共に)。
grep -Po '[\d.]+' file.json |
sort -V |
awk -F. '
{
max[$1] = $0
max[$1"."$2] = $0
}
END {
printf "{"
for (i in max) {
printf c"\"%s\":\"%s\"", i, max[i]
c = ","
}
print "}"
}'