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생각하는 대로 수행되지 않고 문자 그대로 일치합니다 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, $month$day각각에 저장하려면(10진수 정수로, 앞에 오는 0을 신경쓰는 경우 -s 를 제거 %-m하고 2자리 연도도 참조).%-d%y

(GNU와는 반대로 stat, 심볼릭 링크 유형의 파일의 경우 심볼릭 링크 자체의 수정 시간이 아니라 심볼릭 링크 대상의 수정 시간이 고려됩니다. GNU에서는 를 stat사용합니다 stat -L).

관련 정보