ソートコマンド - 毎月のソートは機能しませんか?

ソートコマンド - 毎月のソートは機能しませんか?

タイムスタンプ配列があります。

arr[0]="04-Feb-2021-21-05-48"
arr[1]="18-Jan-2021-12-19-48"
arr[2]="25-Jan-2021-00-24-29"
arr[3]="26-Jan-2021-00-28-33"
arr[4]="04-Feb-2021-21-06-49"
arr[5]="18-Jan-2021-12-19-48"
arr[6]="25-Jan-2021-00-24-29"
arr[7]="26-Jan-2021-00-28-33"

この配列をソートし、次のコマンドを使用してタイムスタンプを新しい配列にソートしたいと思います。

IFS=$'\n' sorted=($(sort -r -t- -k2.1,2.3M <<<"${arr[*]}")); unset IFS
printf "[%s]\n" "${sorted[@]}"

この出力を得ましたが、望む結果ではありません。

[26-Jan-2021-00-28-33]
[26-Jan-2021-00-28-33]
[25-Jan-2021-00-24-29]
[25-Jan-2021-00-24-29]
[18-Jan-2021-12-19-48]
[18-Jan-2021-12-19-48]
[04-Feb-2021-21-06-49]
[04-Feb-2021-21-05-48]

代わりにタイムスタンプを降順に並べ替えたいと思います。
では、この結果をどのように取得できますか?

[04-Feb-2021-21-06-49]
[04-Feb-2021-21-05-48]
[26-Jan-2021-00-28-33]
[26-Jan-2021-00-28-33]
[25-Jan-2021-00-24-29]
[25-Jan-2021-00-24-29]
[18-Jan-2021-12-19-48]
[18-Jan-2021-12-19-48]

このバージョンのソートコマンドを試しましたが、そのうち何も機能しませんでした...

IFS=$'\n' sorted=($(sort -r -t- -k3.1,3.4 -k2.1,2.3M <<<"${arr[*]}")); unset IFS
IFS=$'\n' sorted=($(sort -r -t- -k2.1,2.3M <<<"${arr[*]}")); unset IFS
IFS=$'\n' sorted=($(sort -t- -k2.1,2.3M <<<"${arr[*]}")); unset IFS

修正する

月フィールドに基づいてタイムスタンプ配列を並べ替えるのではなく、タイムスタンプを降順に並べ替えたいことを明確にするために質問を更新しました。

乾杯。

答え1

指定した列にのみ「reverse」を適用する場合に指定します。後ろにこれ-k

sort -t- -k2.1,2.3Mr
#                  ~

答え2

-r反転したいキーに反転を使用しますが、必要な出力を得るにはこの方法を試してください。複雑なsort' を使用する代わりに、文字列を適切な日付形式に変換してソートしてから、元の形式に戻って複雑にしましょう。

printf "%s\n" "${sorted[@]}" | \
  awk -F'-' '{ print $1" " tolower($2)" "$3" "$4":"$5":"$6 }' | \ # 04 feb 2021 21:05:48
  xargs -I {} date -d {} +"%Y-%m-%d %H:%M:%S" | \ # 2021-02-04 21:05:48
  sort -k1r | \
  xargs -I {} date -d {} +"[%d-%b-%Y-%H-%M-%S]"

出力:

[04-Feb-2021-21-06-49]
[04-Feb-2021-21-05-48]
[26-Jan-2021-00-28-33]
[26-Jan-2021-00-28-33]
[25-Jan-2021-00-24-29]
[25-Jan-2021-00-24-29]
[18-Jan-2021-12-19-48]
[18-Jan-2021-12-19-48]

答え3

いくつかのパール:

printf '%s\n' "${arr[@]}" \
| perl -MTime::Piece -lne '
    $t = Time::Piece->strptime($_, "%d-%b-%Y-%H-%M-%S");
    push @dates, [$t, $_];
    END {print for map {$_->[1]} sort {$b->[0] <=> $a->[0]} @dates}
  '

答え4

@ilkkachuが指摘したように、基本的に各キーの開始位置と停止位置は最初と終了位置であるため、私の場合は-k3,3r代わりに省略できます-k3.1,3.4r

@chorobaのソリューションsort -t- -k2.1,2.3Mrは私の問題を解決するのに最も役立ちました。実際、「月」フィールドに基づいてソートするときにキーに-rを含める必要があるようです...だからではありませんがsort -t- -k2,2Mrsort -r -t- -k2,2M

@altblue によって生成された月フィールドだけでなく、タイムスタンプを降順にソートする必要があることを明確にした後、全体的に最良の答えは次のとおりです。

sort -t- -k3,3nr -k2,2Mr -n -r

-rしかし、今年の鍵には必要ないと思います-k3,3nr。 @Toby Speightが述べたように、keydefに修飾子を指定すると、そのkeydefの修飾子がリセットされるため、ウォール-rキーが必要になるようです。したがって、タイムスタンプを降順にソートするには、「グローバル」キー定義と「月」キー定義を指定する必要があります。-k2,2MrMr-rMr

有用な答えをすべて考慮し、追加のテストを実行した後、私の場合は数字の順序を指定する必要はなく、-k3,3年と月ごとに並べ替えるだけで十分であることがわかりました-k2,2Mr

sort -r -t- -k3,3 -k2,2Mr

関連情報