我的脚本接收的一个参数是以以下格式给出的日期: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 中定义一个匹配你需要的格式的正则表达式。这样你就可以执行以下操作:
That is, you can define a regex in Bash matching the format you want. This way you can do:
[[ "$date" =~ ^regex$ ]] && echo "matched" || echo "did not match"
如果测试成功,则执行&&
后的命令,如果测试失败,则执行||
后的命令。
请注意,这是基于Aleks-Daniel Jakimenko在在bash中验证用户输入日期格式的解决方案中的解决方案。
在其他shell中,您可以使用grep。如果您的shell符合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 的正则表达式检查没有此问题。
sh
、fish
或其他功能较少的shell,使用grep似乎是最好的选择。 - tomekwigrep
的解决方案接受多行值,其中每行包含一个日期:例如 printf '%s\n%s\n' "$date" "$date" | grep …
将被接受,这可能不是预期的。 - joki&&
,我称之为原子批处理,因为它将左右值转换为一个原子批处理)。虽然它比if语句不太易读,但在我看来,它非常节省空间,通常值得权衡。谢谢。 - Nate T在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') ]
date -d 2017-11-14e
,它会返回 Tue Nov 14 05:00:00 UTC 2017,但那会破坏我的脚本。 - Josiah=~
Bash 运算符除其他答案之外,还支持扩展正则表达式(ERE)——扩展正则表达式。#!/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
或 正则表达式测试
# 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。
date
解析它,并要求date
将字符串转换为正确的格式。如果两个字符串相同,则您具有有效的格式和有效的日期。if [[ "$datestr" == $(date -d "$datestr" "+%Y%m%d" 2>/dev/null) ]]; then
echo "Valid date"
else
echo "Invalid date"
fi