在 OSX 上,我正在构建一个函数来验证日期格式,然后将它们转换为纪元时间。该函数应验证日期是否采用以下格式之一(如果没有错误): 01/01/1970 10:00PM
或10: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