현재는 2019년 8월 14일이며 날짜 목록(dd.mm.yyyy)이 포함된 텍스트 파일이 있습니다.
30.07.2018
14.08.2019
18.08.2019
20.08.2019
01.01.2020
목록에 있는 날짜는 마감일입니다.
출력은 다음과 같아야 합니다. 현재 날짜보다 이전 날짜와 10일 후에 만료되는 날짜 목록(1~10일 내에 만료되는 경우 나열되고, 오늘 만료되는 경우에도 나열됩니다.) 11일 이상 이후의 만료가 목록에 없는 경우).
답변1
GNU 사용 date
:
#! /bin/sh -
printf '%s days\n' -1 +10 |
date -f - +%d.%m.%YT |
sort -nt. -k3 -k2 -k1 -- - "$@" |
sed '/T/,/T/!d;/T/d'
아이디어는 어제와 10일 후의 날짜를 삽입하고 로 끝나는 목록을 정렬하는 것입니다. T
예를 들어 2019-08-14에 실행하는 경우 다음과 같은 결과를 얻습니다.
30.07.2018
13.08.2019T
14.08.2019
18.08.2019
20.08.2019
24.08.2019T
01.01.2020
우리는 이 두 줄 사이의 부분을 추출합니다 T
.
$ faketime 2019-08-14 that-script your-file
14.08.2019
18.08.2019
20.08.2019
답변2
GNU를 사용 awk
하거나 다음을 수행하십시오 mawk
.
$ cat file
30.07.2018
13.08.2019
14.08.2019
18.08.2019
20.08.2019
21.08.2019
23.08.2019
24.08.2019
25.08.2019
01.01.2020
$ awk -f script.awk file # running this on 2019-08-14
30.07.2018 expired 380 days ago
13.08.2019 expired 1 days ago
14.08.2019 expires in 0 days
18.08.2019 expires in 4 days
20.08.2019 expires in 6 days
21.08.2019 expires in 7 days
23.08.2019 expires in 9 days
24.08.2019 expires in 10 days
그러면 입력 데이터와 동일한 순서로 날짜가 출력되며 각각 탭과 짧은 메시지 접미사가 포함됩니다. 11일 이상의 미래 날짜는 출력되지 않습니다.
스크립트 awk
:
BEGIN {
FS = "."
now = systime()/(24*60*60) - 1
}
{
datespec = sprintf("%s %s %s 00 00 00", $3, $2, $1)
timestamp = mktime(datespec)/(24*60*60)
diff = timestamp - now
if (diff < 0)
message = sprintf("expired %d days ago", 1 - diff)
else if (diff < 11)
message = sprintf("expires in %d days", diff)
else
next
printf("%s\t%s\n", $0, message)
}
mawk
GNU는 awk
날짜/시간 관련 기능을 확장했습니다. 여기서는 systime()
UNIX 타임스탬프를 사용하여 현재 시간(1970년 1월 1일 00:00 이후의 초 수)을 가져옵니다. 하루의 초 수로 나누어 하루 전체로 반올림합니다.
각 입력 행에 대해 점으로 구분된 세 개의 숫자를 사용하여 mktime()
특정 날짜의 자정(하루의 시작)에 대한 UNIX 타임스탬프를 생성하고 이를 완전한 일 수로 반올림한 후 이라고 now
부릅니다 timestamp
.
그런 다음 차이점을 기준으로 비교 now
하고 timestamp
무엇을 인쇄할지 결정하는 문제입니다.
GNU 문서를 참조 awk
하거나 mawk
문서화 방법을 확인 systime()
하세요 mktime()
.
해당 UNIX 타임스탬프를 계산하고, 날짜 앞에 이 값을 붙이고, 숫자로 정렬하고, 현재 사용되는 타임스탬프를 삭제하여 날짜를 정렬합니다( mawk
또는 GNU 사용 awk
).
$ awk -F . -v OFS="\t" '{ print mktime(sprintf("%d %d %d 00 00 00", $3, $2, $1)), $0 }' file | sort -n | cut -f 2
30.07.2018
13.08.2019
14.08.2019
18.08.2019
20.08.2019
21.08.2019
23.08.2019
24.08.2019
25.08.2019
01.01.2020
똑같지만 더 간단하고 BSD에서도 작동합니다 awk
.
$ awk -F . -v OFS="\t" '{ print sprintf("%s-%s-%s", $3, $2, $1), $0 }' file | sort | cut -f 2
30.07.2018
13.08.2019
14.08.2019
18.08.2019
20.08.2019
21.08.2019
23.08.2019
24.08.2019
25.08.2019
01.01.2020
날짜를 YYYY-MM-DD(ISO 8601 달력 날짜) 형식을 취하고 UNIX 타임스탬프 대신 사전순으로 정렬됩니다.
처음부터 YYYY-MM-DD 날짜 형식을 사용하면 정렬이 훨씬 간단해지지만 awk
"오늘은 10일 미만의 미래"라고 (쉽게) 말할 수 있으려면 여전히 위의 첫 번째 스크립트와 동일한 계산을 수행해야 합니다. ".
답변3
내가 당신을 잘 이해한다면 이것을 생각하고 @Kunasalanda의 답변을 예로 사용했습니다.
이는 bash(또는 호환 가능한 쉘) 및 GNU 날짜를 사용하여 수행됩니다. 예를 들어 macOS(GNU가 아닌 날짜)에서는 실패합니다.
today=$(date -d $(date +'%Y-%m-%d') +%s)
while read i; do
[[ -z "$i" ]] && continue
date_format=$(echo "$i" | awk -F'.' -vOFS='-' '{print $3,$2,$1}')
convert_date=$(date -d "$date_format" +%s)
if [[ "$convert_date" -ge "$today" ]]; then
expires=$(( ("$convert_date"- "$today")/86400 ))
[[ ! "$expires" -gt 10 ]] && echo $i expires in $expires days
fi
done < file
산출:
14.08.2019 expires in 0 days
18.08.2019 expires in 4 days
20.08.2019 expires in 6 days
빈 줄 무시
[[ -z "$i" ]] && continue
작업을 수행할 수 있도록 dd.mm.yy
포맷 됨yyyy-mm-dd
date_format=$(echo "$i" | awk -F'.' -vOFS='-' '{print $3,$2,$1}')
날짜를 초로 변환
convert_date=$(date -d "$date_format" +%s)
오늘보다 이후의 날짜만 선택하세요.
if [[ "$convert_date" -ge "$today" ]]; then
특정 날짜의 만료일까지 남은 일수를 가져옵니다.
expires=$(( ("$convert_date"- "$today")/86400 ))
만료 시간이 10일 미만인 경우에만 출력
[[ ! "$expires" -gt 10 ]] && echo "$i" expires in "$expires" days