Pregunta

I want foo() compliant with an extended regex or like brace expansion.

Solution based on egrep:

foo() 
{
  egrep -sq "$2" <<< "$1" && echo "string '$1' matches pattern '$2'"
}

$ foo bar '.*r'
string 'bar' matches pattern '*r'
$ foo bar '.*r|.*s'
string 'bar' matches pattern '*r|*s'

But I also want a 100% bash solution. My attempt:

foo() 
{
  [[ "$1" = $2 ]] && echo "string '$1' matches pattern '$2'"
}

Basic pattern is OK:

$ foo bar '*r'
string 'bar' matches pattern '*r'

But what is the appropriate formatting to use to detect alternation / extended pattern?

$ foo bar '*(r|s)'
$ foo bar '*\(r|s\)'
$ foo bar '*\(r\|s\)'
$ foo bar '*\{r,s\}'
$ foo bar '*{r,s}'

Moreover bash manpage says:

[[ expression ]]
Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed.

  1. Is there a trick to use extended regex/pattern within [[ ]] statement?
  2. How would you implement a such function?
¿Fue útil?

Solución

You need to use the =~ operator.

From man bash:

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly.

Try this:

foo() 
{
  [[ "$1" =~ $2 ]] && echo "string '$1' matches pattern '$2'"
}

Also note that * is a wildcard (and undergoes "pattern matching") while .* is a regular expression.

Change your example to:

$ foo bar '.*(r|s)'
string 'bar' matches pattern '.*(r|s)'

Otros consejos

You mean this?

[[ 'bar' == *[rs] ]] && echo yes || echo no # this is simple globbing

Or using extglobs:

shopt -s extglob
[[ 'bar' == @(*r|*s) ]] && echo yes || echo no

For more info you can read bash hackers page about pattern matching

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top