매월 말일을 기준으로 행을 인쇄하는 방법

매월 말일을 기준으로 행을 인쇄하는 방법

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...날짜 스탬프를 대시로 분할하여 임시 배열을 만듭니다. 그런 다음 분할 부분에서 두 개의 새 필드 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의 기능 중 하나는 다음을 지원하는 기능이 내장되어 있다는 것입니다.ISO 8601 Date에스. 즉 Date, 값을 호출하면 그 유효성이 확인됩니다. 따라서 주어진 데이터세트에서는 2024-02-29잘 작동하지만 오류가 2024-02-30발생합니다 .Day out of range

위 코드는 행이 날짜 순서가 아니더라도 제대로 작동합니다.

  1. header( ) 를 읽은 lines[0]후 즉시 출력합니다 put.
  2. 열의 나머지 lines내용을 읽고 배열에 저장합니다.split|@a
  3. 세 번째(날짜) 열을 $b스칼라에 복사합니다.
  4. 내장 Date및 루틴을 사용하여 month월별 스칼라를 계산하고 다음을 사용하여 classify날짜 및 행 번호를 반환합니다.$b:as$++~처럼해시 =>에 저장된 {키 값} 쌍입니다.%c
  5. 요소별로 Hash map로 이동하여 %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

참고: 때로는 언어에 대한 데이터의 내부 표현을 보는 것이 도움이 되므로 %c4단계 이후의 해시는 다음과 같습니다(월별로 정렬).

~$ 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

관련 정보