脚本收到的参数之一是以下格式的日期:yyyymmdd
。
我想检查我是否得到一个有效的日期作为输入。
我该怎么做?我正在尝试使用一个正则表达式,如:[0-9]{8}
您可以使用测试结构[[ ]]
和正则表达式匹配运算符=~
来检查字符串是否与正则表达式模式匹配(文档)。
对于您的具体情况,您可以写:
[[ "$date" =~ ^[0-9]{8}$ ]] && echo "yes"
或者更准确的测试:
[[ "$date" =~ ^[0-9]{4}(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])$ ]] && echo "yes"
# |______/______*______/______*__________*______/|
# | | | | |
# | | | | |
# | --year-- --month-- --day-- |
# | either 01...09 either 01..09 |
# start of line or 10,11,12 or 10..29 |
# or 30, 31 |
# end of line
也就是说,您可以在Bash中定义一个正则表达式,以匹配您想要的格式。你可以这样做:
[[ "$date" =~ ^regex$ ]] && echo "matched" || echo "did not match"
其中如果测试成功则执行&&
之后的命令,如果测试不成功则执行||
之后的命令。
请注意,这是基于Aleks Daniel Jakimenko在bash中的用户输入日期格式验证中的解决方案。
在其他shell中,您可以使用grep。如果您的外壳符合POSIX,请执行
(echo "$date" | grep -Eq ^regex$) && echo "matched" || echo "did not match"
在不符合POSIX的fish中,您可以执行
echo "$date" | grep -Eq "^regex$"; and echo "matched"; or echo "did not match"
注意事项:这些便携式grep解决方案不防水例如,它们可能被包含换行符的输入参数欺骗。第一个提到的特定于bash的regex检查没有这个问题。
在bash版本3中,您可以使用'=~'运算符:
if [[ "$date" =~ ^[0-9]{8}$ ]]; then
echo "Valid date"
else
echo "Invalid date"
fi
参考:http://tldp.org/LDP/abs/html/bashver3.html#REGEXMATCHREF
注意:从Bash 3.2版起,不再需要在双括号[[]]内的匹配运算符中引用
测试字符串是否为正确日期的一个好方法是使用命令date:
if date -d "${DATE}" >/dev/null 2>&1
then
# do what you need to do with your date
else
echo "${DATE} incorrect date" >&2
exit 1
fi
来自评论:可以使用格式化
if [ "2017-01-14" == $(date -d "2017-01-14" '+%Y-%m-%d') ]
除了=~
Bash运算符的其他答案之外-扩展正则表达式(ERE)。
这是
awk
和egrep
(或grep -E
)以及Bash的[[ ... =~ ... ]]
运算符使用的语法。
例如,一个支持在多个参数中提供多个测试的函数:
#!/bin/bash
#-----------#
# Functions #
#-----------#
function RT
{
declare __line;
for __line in "${@:2}";
do
if ! [[ "$__line" =~ $1 ]];
then
return 1;
fi
done
return 0;
}
#-----------#
# Main #
#-----------#
regex_v='^[0-9]*$';
value_1_v='12345';
value_2_v='67890';
if RT "$regex_v" "$value_1_v" "$value_2_v";
then
printf 'Valid';
else
printf 'Invalid';
fi
说明
函数RT
或Regex Test
# Declare a local variable for a loop.
declare __line;
# Loop for every argument's value except the first - regex rule
for __line in "${@:2}";
# Test the value and return a **non-zero** return code if failed.
# Alternative: if [[ ! "$__line" =~ $1 ]];
if ! [[ "$__line" =~ $1 ]];
# Return a **zero** return code - success.
return 0;
主要代码
# Define arguments for the function to test
regex_v='^[0-9]*$'; # Regex rule
value_1_v='12345'; # First value
value_2_v='67890'; # Second value
# A statement which runs the function with specified arguments
# and executes `printf 'Valid';` if succeeded, else - `printf 'Invalid';`
if RT "$regex_v" "$value_v";
应该可以指向失败的参数,例如,将计数器附加到循环并将其值打印到stderr
。
相关
=~
运算符右侧的引号会使其变成字符串,而不是RegularExpression。源
如果正则表达式的使用有助于确定日期的字符序列是否正确,则无法轻松使用它来确定日期是否有效。以下示例将传递正则表达式,但都是无效日期:20180231、20190229、20190431
因此,如果您想验证日期字符串(我们称之为datestr
)的格式是否正确,最好使用date
进行解析,并要求date
将字符串转换为正确的格式。如果两个字符串相同,则表示您具有有效的格式和有效的日期。
if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi