[Linux 셸 스크립트] 날짜 처리 - 054 윤년인지 확인하기
본문 바로가기
IT 이야기/Linux 셸 스크립트

[Linux 셸 스크립트] 날짜 처리 - 054 윤년인지 확인하기

by 찬찬이 아빠 2021. 3. 29.
반응형
  1. 사용 명령어

(1) expr

(2) test

(3) ls

 

 

  2. 키워드 & 사용처

(1) 키워드

윤년, 나머지

 

(2) 사용처

2월 말에 작성된 로그 파일을 선택하고 싶을 때 사용합니다.

 

 

  3. 실행 예제
$ ./leapyear.sh
leap year: 2012
/var/log/myapp/access.log-20120229

 

 

  4. 스크립트

#!/bin/sh

 

# 네 자리 년도 얻기

year=$(date '+%Y')         

 

logfile="/var/log/myapp/access.log-"

 

# 년도를 나눈 나머지 계산

mod1=$(expr $year % 4)         

mod2=$(expr $year %100)       

mod3=$(expr $year % 400)     

 

# 윤년인지 판정

if [ $mod1 -eq 0 -a $mod2 -ne 0 -o $mod3 -eq 0 ]; then         

    echo "leap year: $year"

    ls "${logfile}${year}0229"            

else

    echo "not leap year: $year"

    ls  "${logfile}${year}0228"         

fi

 

 

  5. 해설

이 스크립트는 2월 말일 파일을 표시하기 위해 올해가 윤년인지 판별합니다. access.log-20120315 처럼 파일명에 년월일이 있는 로그 파일이 /var/log/myapp 디렉터리에 저장되어 있다고 가정합니다.

 

월말에 로그 파일을 참조해서 월별 처리를 하는 일이 많을 겁니다. 예제처럼 파일명에 날짜가 적힌 로그 파일을 다룰 때 2월 말인지 판단하는 것은 프로그래머의 공통된 고민거리입니다.

 

우선 윤년인지 판정하는 조건은 아래와 같습니다.

1. 서력이 4로 나눠 떨어지면 윤년

2. 단, 100으로 나눠 떨어지면 윤년이 아님

3. 단, 400으로 나눠 떨어지면 윤년

 

특히 세 번째 조건은 알 알려지지 않아서 2000년에 많은 버그가 발생했던 원인이 되기도 했습니다.

 

우선 에서 서력을 네 자리로 취득해서 셸 변수 year에 대입합니다. 에서 년도를 나눈 나머지를 expr 명령어로 계산합니다. expr 명령어로 % 연산자를 써서 나머지를 계산하는데 조건 1, 2, 3의 각 나머지 값을 셸 변수 mod1, mod2, mod3에 대입합니다.

 

에서는 앞에선 본 윤년 조건을 if문으로 판정합니다. 나눠 떨어진다라는 것은 나머지가 0이라는 뜻이므로 0과 변숫값을 비교합니다. 값이 같은지는 -eq 연산자로, 같지 않은지는 -ne 연산자로 판별합니다. -a는 AND, -o는 OR을 뜻합니다. ③ 조건식은 "mod1 값이 0이고 mod2 값은 0이 아니다" 또는 "mod3이 0"이라는 조건을 뜻합니다.

 

아래는 test 비교 연산자를 나타냅니다.

표기 의미
변수1 -eq 변수2 변수1과 변수2가 같으면 참
변수1 -ne 변수2 변수1과 변수2가 다르면 참
변수1 -lt 변수2 변수1이 변수2 미만이면 참
변수1 -le 변수2 변수1이 변수2 이하이면 참
변수1 -gt 변수2 변수1이 변수2 초과면 참
변수1 -ge 변수2 변수1이 변수2 이상이면 참

 

lt는 "less than", le는 "less than or equal to", gt는 "greater than", ge는 "greater than or equal to"입니다.

 

이렇게 하면 윤년 판정이 되므로 2월 말일 파일을 선택할 수 있습니다. ④와 ⑤에서 윤년일 때는 2월 29일 로그 파일을, 윤년이 아니면 2월 28일 로그 파일을 ls 명령어로 표시합니다.

 

 

<주의사항>

test 명령어의 -a(AND)와 -o(OR) 연산자 우선 순위는 다른 프로그래밍 언어와 마찬가지로 AND가 OR보다 우선입니다. 만약 OR 우선도를 AND보다 높이고 싶으면 괄호를 둘러쌉니다. 이때 셸이 괄호를 해석하지 않도록 \로 이스케이프해서 \(... \)처럼 사용합니다.

# 앞에 있는 -a(AND)보다 -o(OR)가 우선 처리됨
if [ $a -eq 0 -a \ ( $b -ne 0 -o $c -eq 0 \) ]; then

"$a가 0이고, 4b가 0이 아니거나 $c가 0"일 때 참이 됩니다. test 명령어는 셸 내장과 외부 명령어 두 종류가 있는데 셸 스크립트는 셸 내장 test 명령어가 사용됩니다. 따라서 man sh로 셸 매뉴얼을 보면 test 명령어 설명이 나옵니다.

 

 

참고서적 : 유닉스 리눅스 셸 스크립트 예제 사전

반응형

댓글