쉘 스크립트에서 여러 날짜와 시간 비교

쉘 스크립트에서 여러 날짜와 시간 비교

jq 명령의 다음 출력이 있고 모든 날짜와 시간을 비교하여 어느 것이 최신인지 알려주고 싶습니다.

Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Thu Mar  2 05:55:07 2023
Tue Feb 28 16:02:40 2023

이 작업을 수행하는 방법을 안내해 주세요. 두 날짜를 비교하는 데 여러 답변이 있는 것 같습니다. 날짜와 시간을 비교하는 방법과 위의 타임스탬프를 특정 형식으로 변환해야 하는지 잘 모르겠습니다.

안내해주세요

안녕하세요, 사무라이

답변1

다음과 같은 JSON 문서가 있다고 가정해 보겠습니다.

[
   { "datestring": "Mon Feb 20 09:22:25 2023" },
   { "datestring": "Mon Feb 20 17:42:13 2023" },
   { "datestring": "Thu Mar  2 05:55:07 2023" },
   { "datestring": "Tue Feb 28 16:02:40 2023" }
]

(질문의 데이터를 사용하여 이를 생성할 수 있지만 jq -Rn '[inputs] | map({datestring: .})'일부 JSON 문서에 이 데이터가 이미 있다고 가정합니다.)

...그런 다음 및 를 사용하여 jq이러한 날짜 문자열을 Unix 타임스탬프(정수)로 변환한 다음 이러한 타임스탬프를 정렬 키로 사용하여 원래 문자열을 정렬할 수 있습니다.strptime()mktime

jq 'sort_by(.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)' file

그러면 예제 문서의 최상위 배열에 있는 각 항목에 대한 Unix 타임스탬프가 계산됩니다. 주어진 특정 형식 문자열을 사용하여 주어진 날짜 문자열을 구문 분석하고( strptime()이 형식 문자열의 의미는 시스템 설명서 참조) 결과 시간 표현을 를 사용하여 항목을 오름차순으로 정렬하는 Unix 타임스탬프로 변환합니다.strptimemktimesort_by()

위의 예제 문서를 보면 다음과 같은 결과가 생성됩니다.

[
   { "datestring": "Mon Feb 20 09:22:25 2023" },
   { "datestring": "Mon Feb 20 17:42:13 2023" },
   { "datestring": "Tue Feb 28 16:02:40 2023" },
   { "datestring": "Thu Mar  2 05:55:07 2023" }
]

약간 더 효율적인 접근 방식은 Unix 타임스탬프를 미리 계산하여 정렬에 사용한 다음 다시 삭제하는 것입니다(a슈워츠 변환):

jq 'map(.ts = (.datestring|strptime("%a %b %e %H:%M:%S %Y")|mktime)) | sort_by(.ts) | map(del(.ts))' file

답변2

명령을 사용하여 date이러한 날짜를 Unix 타임스탬프로 변환하고 정렬한 다음 원하는 형식으로 다시 변환할 수 있습니다.

예를 들어 날짜를 타임스탬프로 변환한 후 다시 되돌립니다.

date -d "Mon Feb 20 09:22:25 2023" +%s
1676884945
date -d "@1676884945" +%c
Mon Feb 20 09:22:25 2023
  • -d@표시 문자열에 표시된 날짜/시간을 나타냅니다. Unix 시간을 사용하는 경우 시간 앞에 넣어야 합니다.
  • +%s날짜가 UNIX epoch 시간으로 표시됨을 나타냅니다.
  • +%c날짜가 로케일 시간 형식으로 표시됨을 나타냅니다.

그런 다음 이를 루프에 넣고 시간을 Unix 시대로 변환하고 쉽게 정렬하고 정렬된 시간을 원하는 시간 형식으로 다시 변환할 수 있습니다.

날짜 파일에 날짜가 있으면 이를 유닉스 타임스탬프로 변환하고 정렬합니다.

while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n

그런 다음 정렬된 형식을 원하는 형식으로 다시 변환할 수 있습니다.

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +%c; done

당신이 준 예를 들어, 당신은 다음과 같은 것을 얻을 것입니다

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +%c; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar  2 05:55:07 2023

%c를 사용하면 로케일과 일치하는 형식으로 출력되므로 원하는 형식이 필요하지 않습니다.

예제에서 형식을 가져왔는지 확인하려면 다음을 사용해야 합니다.+'%a %b %d %T %Y'

for i in $(while IFS= read -r line; do date -d "$line" +%s; done < datefile  | sort -n); do date -d "@$i" +'%a %b %d %T %Y'; done
Mon Feb 20 09:22:25 2023
Mon Feb 20 17:42:13 2023
Tue Feb 28 16:02:40 2023
Thu Mar 02 05:55:07 2023
  • %a세 글자의 날(Three Letter Day)의 약어
  • %b약어로 된 세 글자의 달
  • %d한 달의 하루
  • %T앞에 0이 붙은 시간
  • %Y년도

20230220092225연도, 월, 일, 시간 등과 같은 모든 숫자를 공백 없이 변환하고 '%Y%m%dH%M%S'해당 형식을 사용하여 날짜를 정렬하거나 비교할 수도 있습니다.

date -d "Mon Feb 20 09:22:25 2023" +'%Y%m%d%H%M%S'
20230220092225

답변3

GNU sort또는 호환 버전을 사용하면 다음을 사용하여 입력을 시간순으로 정렬할 수 있습니다.

LC_ALL=C sort -b -k5,5rn -k2,2rM -k3,3rn -k4,4r

여기에서는 r최신 항목부터 오래된 항목 순으로 정렬되어 있으므로 head -n1파이프를 통해 최신 항목을 얻을 수 있습니다. 비표준 부분은 M두 번째 정렬 키에 대한 플래그로, 월 이름이나 약어를 기준으로 정렬하는 데 사용됩니다(여기에서는 LC_ALL=C영어를 강제로 사용하는 데 사용됨).

jq시간 구문 분석 및 형식 지정 기능이 있으므로 참고하세요 .출력을 생성하는 호출에서 직접 jq날짜 배열을 정렬 할 수 있어야 합니다.jq첫 번째.

관련 정보