어느 달의 절반인지 감지하는 Unix 쉘 프로그램입니다. 매월 특정 날짜(dom) -le 16

어느 달의 절반인지 감지하는 Unix 쉘 프로그램입니다. 매월 특정 날짜(dom) -le 16

최종 목표는 변수 YYYYMMDD를 설정하는 것입니다. 여기서 DD는 두 변수(01 또는 16) 중 하나입니다.

두 값 중 하나로 변수를 생성하려고 합니다.

이것이 내가 지금까지 가지고 있는 것이지만 작동하지 않습니다.

DYA=date +%d 
DYB=IF [["$DYA" -ge 16]]; then 16
else 01
fi
YR=2020
MO=03

FD="$YR$MO$DY"
ECHO "$FD"

답변1

bash버전 4.2 이상 사용 :

#!/bin/bash

printf -v day '%(%e)T' -1

if [[ $day -lt 16 ]]; then
    # 1st half of the month
    day=01
else
    # 2nd half of the month
    day=16
fi

printf '%(%Y%m)T%s\n' -1 "$day"

첫 번째는 printf이번 달의 날짜를 10진수로 변수에 인쇄합니다 day. 이러한 if명령문은 해당 값으로 제한되거나 01해당 16값에 따라 제한됩니다.

마지막 것은 printf현재 연도와 월을 인쇄한 다음 그 끝에 01or 문자열을 추가합니다.16

-1호출에 대한 인수는 printf형식 %(...)T문자열이 현재 시간을 형식화된 타임스탬프로 사용하도록 합니다( bash4.3 이상을 사용하는 경우 첫 번째 호출에서는 암시적이므로 이를 엄격히 요구하지 않습니다).

더 컴팩트한 버전 bash:

#!/bin/bash

printf -v day '%(%e)T' -1
printf '%(%Y%m)T%.2d\n' -1 "$(( (day < 16) ? 1 : 16 ))"

여기에서는 공개 함수를 사용하여 산술 확장 테스트를 수행합니다.삼항 연산자 ?:. 16보다 작 1으면 $day결과는 문자열이고, 1616보다 크면 결과는 문자열입니다. 그런 다음 산술 확장의 결과는 0으로 채워진 정수 형식으로 지정되고 현재 연도와 월 뒤에 삽입됩니다.


귀하의 코드와 관련하여 :

  • [[ ... ]]양쪽에 공백이 필요하다는 점에 유의하세요(음, 명령 종결자이므로 공백 없이 즉시 나타날 수 있습니다).[[]];
  • date명령의 출력을 변수에 넣으 려면 명령 대체를 사용하십시오 day=$( date +%e ). if이는 값을 출력하는 것이라면 귀하의 명령문에 해당됩니다(그러나 그렇지 않습니다).
  • Unix 명령은 대소문자를 구분하므로 ECHO아마도 echo.
  • 시간 형식 출력 및 %d. 산술 문맥(문장)에서 이러한 값을 사용하면 값이 다음과 같이 해석됩니다.0131if01078진수값을 입력하면 08합계 오류가 발생합니다 09(잘못된 8진수입니다). 그래서 나는 %e과 사이에 0이 아닌 패딩된 정수를 얻는 데 사용합니다.131

마지막 요점에 관해서 : 나는 또한 사용할 수 있습니다

printf -v day '%(%d)T' -1

01와 사이에 0 패딩 값을 얻으려면 31다음을 사용해야 합니다.

if [[ 10#$day -ge 16 ]]; then

쉘이 문자열을 8진 정수 대신 10진 정수로 해석하도록 강제합니다.


/bin/sh스크립트 로 ( bash4.2 이전 버전에서도 작동함(예: bashmacOS의 기본 셸):

#!/bin/sh

day=$( date +%e )

if [ "$day" -lt 16 ]; then
    # 1st half of the month
    day=01
else
    # 2nd half of the month
    day=16
fi

date +"%Y%m$day"

표준 쉘에는 형식 문자열이 sh없으므로 날짜 문자열 형식을 사용해야 합니다 . 대신 테스트 에도 사용됩니다 (그리고 변수는 큰따옴표로 묶어야 합니다).%(...)Tbashdate[ ... ][[ ... ]]

더 컴팩트한 버전 /bin/sh:

#!/bin/sh

day=$( date +%e )
printf '%s%.2d\n' "$(date +%Y%m)" "$(( (day < 16) ? 1 : 16 ))"

이 보다 컴팩트한 버전은 컴팩트 bash변형에서 파생되었습니다. 유일한 차이점은 date현재 연도와 월의 형식을 지정하는 것입니다.

답변2

위의 내용을 달성하려면 다음 코드를 사용할 수 있습니다. #touch mycode.sh

#!/bin/bash

export DD=$(date +%d)
export YYYY=$(date | awk '{print $6}')
export MM=$(date +%m)
echo "$YYYY$MM$DD"
if [[ $DD -eq 16 || $DD -eq 01  ]];then

 echo "$DD"

else

 echo " The days are not 1st or 16th "

fi


#sh mycode.sh

출력/출력

20200303

답변3

위의 작업은 다음과 같습니다. 작업 코드는 다음과 같습니다.

export day=$(date +%d)
export YR=$(date | awk '{print $6}')
export MM=$(date +%m)
echo $DY
echo "$YR$MM$day"

if [[ $day -ge 16 ]]; then
    day=16
else
day=01
fi
printf '%(%Y%m)T%s\n' -1 "$day"



export FD="$YR$MM$day"
echo $FD

답변4

dd=$(date +%d)
# values 08 and 09 will not work with arithmetic the way you expect
d=${dd#0}         # remove any leading 0
if [ "$d" -ge 16 ] ;then
  half=16
else
  half=01
fi
date "+%Y%m$half"

이 코드가 가장 이해하기 쉽다고 생각합니다. 유일한 문제는 쉘 산술 표현식과 digital로 시작하는 숫자를 사용하는 것입니다 0. 이는 이전에 접해 본 적이 없다면 아마 깨닫지 못할 것입니다. 형식 문자열은 맨페이지 date에 설명되어 있습니다 . ( 또는 ) 구현 strftime(3)에서는 변환 사양을 이해하지 못합니다 . 구성 은 (또는 다른 셸) 맨페이지의 "매개 변수 확장" 섹션 에 문서화되어 있습니다 .dateprintf%e${dd#0}bash(1)

관련 정보