检查字符串是否与Bash脚本中的正则表达式匹配

时间:2014-01-14 11:43:10

标签: regex bash shell scripting

我的脚本收到的一个参数是以下格式的日期:yyyymmdd

我想检查一下是否有一个有效的日期作为输入。

我该怎么做?我正在尝试使用像[0-9]\{\8}

这样的正则表达式

6 个答案:

答案 0 :(得分:246)

你可以说:

[[ $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     end of line
# start of line            or 10,11,12         or 10..29
#                                              or 30, 31

也就是说,您可以在 bash 中定义匹配所需格式的正则表达式。这样你就可以:

[[ $date =~ ^regex$ ]] && echo "matched" || echo "did not match"

请注意,这是基于Aleks-Daniel Jakimenko在User input date format verification in 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"

答案 1 :(得分:38)

在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起,不再需要在双括号[[]]内的匹配运算符中引用

答案 2 :(得分:27)

测试字符串是否正确日期的好方法是使用命令日期:

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

答案 3 :(得分:1)

我将使用expr match而不是=~

expr match "$date" "^[0-9]\{8\}" >/dev/null && echo yes

这比当前接受使用=~的答案要好,因为=~还将匹配空字符串,恕我直言,它不应该。假设未定义badvar,则[[ "1234" =~ "$badvar" ]]; echo $?给出(不正确)0,而expr match "1234" "$badvar" >/dev/null ; echo $?给出正确的结果1

我们必须使用>/dev/null隐藏expr match输出值,即匹配的字符数;如果找不到匹配的字符,则返回0。请注意,其输出值与它的退出状态不同。如果找到匹配项,则退出状态为0,否则为1。

通常,expr的语法为:

expr match "$string" '$substring'

或者:

expr "$string" : '$substring'

其中$substring是一个正则表达式。

答案 4 :(得分:0)

使用正则表达式可以帮助确定日期的字符序列是否正确,但不能轻松地使用它来确定日期是否有效。以下示例将传递正则表达式,但均为无效日期: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

答案 5 :(得分:0)

除了 =~ Bash 运算符的其他答案 - Extended Regular Expressions (ERE)

<块引用>

这是awkegrep(或grep -E)使用的语法,
以及 Bash 的 [[ ... =~ ... ]] 运算符。

例如,支持多个参数提供的多个测试的函数:

#!/bin/bash

#-----------#
# Functions #
#-----------#

function RT
{
    declare line_l;

    for line_l in "${@:2}"; 
    do 
        if ! [[ "$line_l" =~ $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

说明

函数 RTRegex Test

# Declare a local variable for a loop.

declare line_l;
# Loop for every argument's value except the first whish is a regex rule

for line_l in "${@:2}";
# Test the value and return a **non-zero** return code if failed

if ! [[ "$line_l" =~ $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。< /p>

Source