BASH는 내 정규 표현식을 좋아하지 않습니다

BASH는 내 정규 표현식을 좋아하지 않습니다

파일 수정의 월 2자리, 연도 2자리를 구하려고 하는데 작동하지 않습니다.

modified=$(stat -c %y "$line"); 
# modified="2018-08-22 14:39:36.400469308 -0400"
if [[ $modified =~ ".{2}(\d{2})-(\d{2})" ]]; then
    echo ${BASH_REMATCH[0]}
    echo ${BASH_REMATCH[1]
fi

내가 뭘 잘못했나요?

답변1

첫째, 따옴표는 정규 표현식에서 특수 문자의 의미를 억제합니다(온라인 매뉴얼):

추가 이진 연산자 =~, ... 를 사용하여 패턴의 모든 부분을 인용하여 인용된 부분을 문자열로 일치시킬 수 있습니다. ...정규식 구문에서 특수 문자를 일치시키려면 해당 문자를 인용하여 특수 문자를 제거해야 합니다.

매뉴얼에서는 쉘 구문 분석과 정규식 구문 간의 충돌을 방지하기 위해 정규식을 변수에 넣을 것을 권장합니다.

둘째, \d여러분이 생각하는 대로 작동하지 않고 단지 text 와 일치합니다 d.

또한 ${BASH_REMATCH[0]}인덱싱된 전체 일치 문자열 1과 그 이상은 캡처된 그룹에 포함됩니다.

또한 다음과 같이 4자리 연도를 사용하는 것이 좋습니다.

modified=$(stat -c %y "$file")
re='^([0-9]{4})-([0-9]{2})'
if [[ $modified =~ $re ]]; then
    echo "year:  ${BASH_REMATCH[1]}"
    echo "month: ${BASH_REMATCH[2]}"
else
    echo "invalid timestamp"
fi

오늘 수정된 파일의 경우 year: 2018month: 08. 앞에 0이 있는 숫자는 쉘 및 기타 유틸리티에서 8진수로 처리됩니다.

(1900년대의 날짜를 처리해야 하는 경우 4자리 연도는 문제가 되지 않으며, 월 단위보다는 연도로 식별하기가 더 쉽습니다.)

답변2

이를 위해서는 정규 표현식이 필요하지 않습니다.

$ touch -t 197001010000 myfile
$ ls -l myfile
-rw-rw-r-- 1 jackman jackman 0 Jan  1  1970 myfile
$ IFS='-' read -r year month _rest < <(stat -c %y myfile)
$ echo "$year:${year#??}"$month"
1970:70:01

답변3

대안으로 GNU를 사용하여 date다음을 수행할 수 있습니다.

eval "$(date -r "$file" +'year=%Y month=%-m day=%-d')"

수정 시간의 연도, 월, 일 부분을 및 각각에 저장하려면 $year( $month10 진수 정수로 앞에 0이 표시되는 경우 s를 제거하고 2 자리 연도 $day참조 ).-%-m%-d%y

(GNU와 달리 stat심볼릭 링크 유형 파일의 경우 심볼릭 링크 자체의 수정 시간이 아니라 심볼릭 링크 대상의 수정 시간이 고려됩니다. GNU에서는 stat이것을 사용할 수 있습니다 stat -L).

관련 정보