更重要的是,为了避免这些正则表达式混淆:

更重要的是,为了避免这些正则表达式混淆:

在 OSX 上,我正在构建一个函数来验证日期格式,然后将它们转换为纪元时间。该函数应验证日期是否采用以下格式之一(如果没有错误): 01/01/1970 10:00PM10:00PM(%m/%d/%Y %I:%M%p%I:%M%p)

功能

checkTIME () {
    local CONVERT_CHK_TIME="$1"
    if [[ "$CONVERT_CHK_TIME" =~ ^(0[0-9]|1[0-2]):[0-9][0-9](AM|PM)$ ]]; then
        CONVERT_TIME="$(date -j -f "%I:%M%p" "$CONVERT_CHK_TIME" "+%s")"
    elif [[ "$CONVERT_CHK_TIME" =~ (0[0-9]|1[0-2])\/([0-2][0-9]|3[0-1])\/\d{4}\s[0-9][0-9]:[0-9][0-9](AM|PM) ]]; then
        CONVERT_TIME="$(date -j -f "%m/%d/%Y %I:%M%p" "$CONVERT_CHK_TIME" "+%s")"
    else
        echo "ERROR!"
        exit 1
    fi
}

它目前工作正常,10:00PM但当我尝试时无法匹配01/10/2017 10:00PM

我这样称呼它:

./convert '01/10/2017 10:00PM'
...
...
+ [[ -n 01/10/2017 10:00PM ]]
+ checkTIME '01/10/2017 10:00PM'
+ local 'CONVERT_CHK_TIME=01/10/2017 10:00PM'
+ [[ 01/10/2017 10:00PM =~ ^(0[0-9]|1[0-2]):[0-9][0-9](AM|PM)$ ]]
+ [[ 01/10/2017 10:00PM =~ (0[0-9]|1[0-2])/([0-2][0-9]|3[0-1])/d{4}s[0-9][0-9]:[0-9][0-9](AM|PM) ]]
+ echo 'ERROR!'
ERROR!
+ exit 1

谢谢!

我还尝试了以下正则表达式:

(0[0-9]|1[0-2])\/([0-2][0-9]|3[0-1])\/\d{4}\ [0-9][0-9]:[0-9][0-9](AM|PM)

答案1

如果您有权访问 GNU,一种选择date是让它为您完成繁重的工作并完全避免 RE 复杂性:

checkTIME () {
    convert_time=$(date --date "$1" +'%s' 2>/dev/null)
    if [[ -z "$convert_time" ]]
    then
        echo 'ERROR!'
        exit 1
    fi
}

由于您已告知您无权访问 GNUdate并且需要 RE 来匹配进行验证,因此您可以使用此方法。 (我知道您已经提供了其他几个。)

[[ " $1 " =~ ^' '*([01]?[0-9]/[0123]?[0-9]/2[0-9][0-9][0-9])?' '+([01]?[0-9]:[0-5][0-9][AP]M)?' '*$ ]]

我在输入参数 ( ) 的两侧添加了一个额外的空格,$1以便我们可以匹配任何日期,时间, 或者约会时间(两个组件之间有强制性空间)。正如所写,日期部分需要 2000 年代的四位数年份;请随意放宽这一要求。

我曾经' '指定一个空格。如果您愿意,可以使用它[[:space:]]来表示任何空白。

进行比较后,您可以选择日期部分为${BASH_REMATCH[1]},时间部分为${BASH_REMATCH[2]}

答案2

\d在某些版本的正则表达式(perl)中匹配十进制数字,但在扩展正则表达式用于中命令=~的运算符。[[bash

因此,将 更改\d[0-9]可匹配 4 位十进制数字的模式。

同样对于\s.要匹配一个文字空格字符,请将 替换\s为转义空格 ( \)。如果您想匹配 1 个或多个空白(空格或制表符)然后将\s其替换为[[:blank:]]+.

更重要的是,为了避免这些正则表达式混淆:

man bash表示=~正则表达式根据扩展正则表达式语法,如 中所述regex(3)
man 3 regex(POSIX 正则表达式函数)说SEE ALSO regex(7)
man 7 regex给出了正则表达式语法的描述,并说SEE ALSO POSIX.2, section 2.8 (Regular Expression Notation)

您可以在中找到完整的 POSIX 扩展正则表达式语法。 开放组的Posix 正则表达式文档

答案3

看起来 \d 和 \s 转义符在您的 bash 版本中不起作用。尝试使用[[:digit:]]and[[:space:]]代替。

(0[0-9]|1[0-2])/([0-2][0-9]|3[0-1])/[[:digit:]]{4}[[:space:]](0[0-9]|1[0-2]):[0-9][0-9](AM|PM)

行动中:

bash-3.2$ [[ "01/10/2017 10:00PM" =~ (0[0-9]|1[0-2])/([0-2][0-9]|3[0-1])/[[:digit:]]{4}[[:space:]](0[0-9]|1[0-2]):[0-9][0-9](AM|PM) ]] && echo match
match

答案4

文件 s1 上的此片段:

mydate='01/10/2017 10:00PM'

pl " Expected output:"
cat expected-output1

pl " Results:"
# Linux: dateutils.dconv -f "%s%n" -i "%m/%d/%Y %I:%M%p" "$mydate"
dateconv -f "%s%n" -i "%m/%d/%Y %I:%M%p" "$mydate"

产生:

-----
 Expected output:
1484085600

-----
 Results:
1484085600

在这样的系统上:

OS, ker|rel, machine: Apple/BSD, Darwin 16.7.0, x86_64
Distribution        : macOS 10.12.6 (16G29), Sierra
bash GNU bash 3.2.57

dateconv(又名 dconv、dateutils.dconv)代码是通过brew 提供的 dateutils 包的一部分——dateconv 的一些详细信息:

dateconv - Convert DATE/TIMEs between calendrical systems.
Home    : http://www.fresse.org/dateutils
Path    : /usr/local/bin/dateconv
Version : - ( local: /usr/local/bin/dateconv, 2017-10-15 )
Type    : Mach-O64-bitexecutablex86_64 ...)

最美好的祝愿...干杯,drl

相关内容