How do I use a regex in a shell script?

前端 未结 3 2023
暗喜
暗喜 2020-12-01 10:43

I am trying to match a string with a regex in a shell script. This string is a parameter of the script ( $1 ) and it is a date (MM/DD/YYYY) The regex I\'m trying to use is :

相关标签:
3条回答
  • 2020-12-01 10:51

    To complement the existing helpful answers:

    Using Bash's own regex-matching operator, =~, is a faster alternative in this case, given that you're only matching a single value already stored in a variable:

    set -- '12-34-5678' # set $1 to sample value
    
    kREGEX_DATE='^[0-9]{2}[-/][0-9]{2}[-/][0-9]{4}$' # note use of [0-9] to avoid \d
    [[ $1 =~ $kREGEX_DATE ]]
    echo $? # 0 with the sample value, i.e., a successful match
    

    Note, however, that the caveat re using flavor-specific regex constructs such as \d equally applies: While =~ supports EREs (extended regular expressions), it also supports the host platform's specific extension - it's a rare case of Bash's behavior being platform-dependent.

    To remain portable (in the context of Bash), stick to the POSIX ERE specification.

    Note that =~ even allows you to define capture groups (parenthesized subexpressions) whose matches you can later access through Bash's special ${BASH_REMATCH[@]} array variable.

    Further notes:

    • $kREGEX_DATE is used unquoted, which is necessary for the regex to be recognized as such (quoted parts would be treated as literals).

    • While not always necessary, it is advisable to store the regex in a variable first, because Bash has trouble with regex literals containing \.

      • E.g., on Linux, where \< is supported to match word boundaries, [[ 3 =~ \<3 ]] && echo yes doesn't work, but re='\<3'; [[ 3 =~ $re ]] && echo yes does.
    • I've changed variable name REGEX_DATE to kREGEX_DATE (k signaling a (conceptual) constant), so as to ensure that the name isn't an all-uppercase name, because all-uppercase variable names should be avoided to prevent conflicts with special environment and shell variables.

    0 讨论(0)
  • 2020-12-01 11:10

    the problem is you're trying to use regex features not supported by grep. namely, your \d won't work. use this instead:

    REGEX_DATE="^[[:digit:]]{2}[-/][[:digit:]]{2}[-/][[:digit:]]{4}$"
    echo "$1" | grep -qE "${REGEX_DATE}"
    echo $?
    

    you need the -E flag to get ERE in order to use {#} style.

    0 讨论(0)
  • 2020-12-01 11:15

    I think this is what you want:

    REGEX_DATE='^\d{2}[/-]\d{2}[/-]\d{4}$'
    
    echo "$1" | grep -P -q $REGEX_DATE
    echo $?
    

    I've used the -P switch to get perl regex.

    0 讨论(0)
提交回复
热议问题