BASH 不喜欢我的正则表达式

I w*_*ce. 6 bash regular-expression

我正在尝试获取文件被修改的 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
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

ilk*_*chu 8

首先,引号抑制了正则表达式中特殊字符的含义(在线手册):

一个额外的二元运算符,=~,可用,...模式的任何部分都可以被引用以强制引用的部分作为字符串进行匹配。... 如果您想匹配正则表达式语法中的特殊字符,则必须将其引用以去除其特殊含义。

该手册继续建议将正则表达式放在一个变量中,以防止 shell 解析和正则表达式语法之间发生一些冲突。

其次,\d不会做你认为它会做的事情,而只是匹配一个文字d.

另请注意,${BASH_REMATCH[0]}包含整个匹配字符串,索引1及以上包含捕获的组。

我还强烈建议使用四位数年份,因此:

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
Run Code Online (Sandbox Code Playgroud)

对于今天修改的文件,它给出year: 2018month: 08。请注意,带有前导零的数字将被 shell 和可能的其他实用程序视为八进制。

(如果您需要处理 1900 年代的日期,则四位数年份的问题较少,并且它们更容易识别为年份而不是月份的天数。)