Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a regex in a shell script?

Tags:

regex

bash

shell

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 :

^\d{2}[\/\-]\d{2}[\/\-]\d{4}$ 

It seems to work, I tried it on several regex tests websites.

My shell code is :

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

The "echo $?" returns 1 no matter is the string I'm putting in parameter.

Do you guys have an idea ?

Thanks !

like image 854
Jérôme G Avatar asked Mar 10 '16 14:03

Jérôme G


People also ask

What is regex in shell script?

A regular expression (regex) is a text pattern that can be used for searching and replacing. Regular expressions are similar to Unix wild cards used in globbing, but much more powerful, and can be used to search, replace and validate text.

Can you use regex in bash script?

Regex is a very powerful tool that is available at our disposal & the best thing about using regex is that they can be used in almost every computer language. So if you are Bash Scripting or creating a Python program, we can use regex or we can also write a single line search query.

How does regex work in Linux?

Regular expression is also called regex or regexp. It is a very powerful tool in Linux. Regular expression is a pattern for a matching string that follows some pattern. Regex can be used in a variety of programs like grep, sed, vi, bash, rename and many more.


2 Answers

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.

like image 166
mklement0 Avatar answered Sep 22 '22 18:09

mklement0


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.

like image 27
Chris Lear Avatar answered Sep 21 '22 18:09

Chris Lear