毎月末日に基づいて行を印刷する方法

毎月末日に基づいて行を印刷する方法

Linuxには、次の内容を含むファイルがあります。 col3列の日付値に基づいて、毎月最大日付値を持つ行を印刷したいと思います。データは col3 に基づいて降順にソートされました。

col1|col2|col3
abc|xyz|2024-02-29
hds|fsfs|2024-02-28
fdg|sffe|2024-02-27
dfr|jfdfd|2024-01-31
fdf|gfgfg|2024-01-30
fdg|rgrg|2023-12-31
fgf|yjyjy|2023-12-30
gfgf|hhfdfd|2023-11-28
gfgfg|uysdfd|2023-11-27

予想出力:

abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

答え1

そしてミラー( mlr)file、フィールド区切り文字として(パイプ)を使用して名前付きCSVファイルにデータを読み込むと、フィールド|から年と月を解析し、col3各年と月の組み合わせの最初の値を取得できます。

mlr --csv --fs pipe \
    put 'd = splita($col3, "-"); $y=d[1]; $m=d[2]' then \
    head -n 1 -g y,m then \
    cut -x -f y,m file

ミラーput表現、

d  = splita($col3, "-");
$y = d[1];
$m = d[2];

d...日付スタンプをダッシュ​​に分割して一時的な配列を作成します。次に、パーティションに2つの新しいフィールドy(年)と(月)を作成します。m

次に、head -n 1 -g y,m各年+月グループの最初の値を取得します。

cut最終操作では、y不要になったフィールドを削除します。m

データがソートされていない場合は、最初(または少なくとも前)に追加のheadソートステップを適用する必要があります。

mlr --csv --fs pipe \
    sort -r col3 then \
    put 'd = splita($col3, "-"); $y=d[1]; $m=d[2]' then \
    head -n 1 -g y,m then \
    cut -x -f y,m file

ヘッダーなしのCSV出力を取得するには、対応するmlr--headerless-csv-outputまたは--ho)オプションと一緒に使用してください。


与えられたデータの実行例:

$ mlr --csv --fs pipe --headerless-csv-output sort -r col3 then put 'd = splita($col3, "-"); $y=d[1]; $m=d[2]' then head -n 1 -g y,m then cut -x -f y,m file
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

答え2

sqlite3を使用してすべての操作を実行するシェルスクリプト:

#!/bin/sh

# Filename to process is only arg to script

sqlite3 <<EOF
.mode list
.headers off
.import '$1' data
WITH ranked_dates AS
 (SELECT col1, col2, col3, rank() OVER (PARTITION BY strftime('%Y-%m', col3) ORDER BY col3 DESC) AS date_rank
  FROM data)
SELECT col1, col2, col3
FROM ranked_dates
WHERE date_rank = 1
ORDER BY col3 DESC
EOF

例:

$ ./maxdates dates.txt
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

これは、入力データがすでにソートされていると仮定するのではなく、任意の順序で機能します。

答え3

awkを使って好きなものを選んでください。

$ awk -F'|' 'NR>1 && !seen[substr($NF,1,7)]++' file
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

$ awk 'NR>1 && !seen[substr($0,length()-9,7)]++' file
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

$ awk -F'[-|]' 'NR>1 && !seen[$(NF-2)$(NF-1)]++' file
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

答え4

使用幸せ(以前のPerl_6)

~$ raku -e 'lines[0].put;  my @a = lines.map: *.split: "|";  my $b = @a.map: *.[2];   
            my  %c = $b.classify( { $_.Date.month }, :as{ $_ => $++ } );  
            for %c.map(*.value.max.values).flat.sort -> $n {    
                @a[$n].join("|").put; 
            };'  file

または:

~$ raku -e 'lines[0].put;  my @a = lines.map: *.split: "|";  my $b = @a.map: *.[2];  
            my %c = $b.classify( { $_.Date.month }, :as{ $_ => $++ } ); 
            put @a[$_].join("|") for %c.map(*.value.max.values).flat.sort;'  file

RakuはPerlファミリーのプログラミング言語です。 Rakuの機能の1つは、以下をサポートする機能が組み込まれていることです。ISO 8601 DateS.つまりDate、値を呼び出すとその妥当性が確認されます。したがって、与えられたデータセットでは2024-02-29うまく機能しますが、エラーが2024-02-30発生します。Day out of range

上記のコードは、行が日付順でない場合でも正しく機能します。

  1. header()を読んlines[0]だ直後に出力しますput
  2. 列の残りのlines内容を読み取り、配列に保存します。split|@a
  3. 3番目(日付)列を$bスカラーにコピーします。
  4. 組み込みDateとルーチンを使用してmonth毎月のスカラーを計算し、次を使用してclassify日付と行番号を返します。$b:as$++〜のようにハッシュ=>に格納されている{キー値}のペア。%c
  5. 要素ごとにHashmapに移動して%cBy Monthを選択すると、*.value.max行番号を取得できます(.valuesキー/値を設定する方法なので使用されます)。インデックスを返します(0 3 5 7)
  6. インデックスを繰り返してput元の配列の正しい位置を@a見つけ、join列をにリセットします|

入力例:

col1|col2|col3
abc|xyz|2024-02-29
hds|fsfs|2024-02-28
fdg|sffe|2024-02-27
dfr|jfdfd|2024-01-31
fdf|gfgfg|2024-01-30
fdg|rgrg|2023-12-31
fgf|yjyjy|2023-12-30
gfgf|hhfdfd|2023-11-28
gfgfg|uysdfd|2023-11-27

出力例:

col1|col2|col3
abc|xyz|2024-02-29
dfr|jfdfd|2024-01-31
fdg|rgrg|2023-12-31
gfgf|hhfdfd|2023-11-28

注:時には言語のデータの内部表現を見ることが役に立つので、%cステップ4以降のハッシュは次のようになります(月ごとにソート)。

~$ raku -e 'lines[0].skip; my @a = lines.map: *.split: "|"; my $b = @a.map: *.[2];  my %c = $b.classify( { $_.Date.month }, :as{ $_ => $++ } ); say %c.sort(*.key.Int);'  file
(1 => [2024-01-31 => 3 2024-01-30 => 4] 2 => [2024-02-29 => 0 2024-02-28 => 1 2024-02-27 => 2] 11 => [2023-11-28 => 7 2023-11-27 => 8] 12 => [2023-12-31 => 5 2023-12-30 => 6])

https://docs.raku.org/type/Date https://docs.raku.org/言語/hashmap#Mutable_hashes_and_immutable_maps https://raku.org

関連情報