简体   繁体   中英

Bash regex using bash_rematch not capturing as expected

I'm trying to capture BAR_BAR in FOO_FOO_FOO_BAR_BAR using the following regex: (?:.*?_){3}(.*) .

The regular expression works when using a validator such as RegExr or regex101, but Bash doesn't return anything when I run:

text="FOO_FOO_FOO_BAR_BAR"
regex="(?:.*?_){3}(.*)"

[[ $text =~ $regex ]] && echo "${BASH_REMATCH[1]}"

When I run the following example regex it works perfectly (returning b ):

text="abcdef"
regex="(b)(.)(d)e"
[[ $text =~ $regex ]] && echo "${BASH_REMATCH[1]}"

I'm new to using regex in Bash, what am I missing here?

POSIX regex does not support non-capturing groups and lazy quantifiers. Bash uses POSIX ERE, so you can use

text="FOO_FOO_FOO_BAR_BAR"
regex="([^_]*_){3}(.*)"
[[ $text =~ $regex ]] && echo "${BASH_REMATCH[2]}"
# => BAR_BAR

Here,

  • ([^_]*_){3} - matches three occurrences (Group 1) of any zero or more chars other than _ followed with a _ char
  • (.*) - the rest of the string (Group 2).

As in this case a capturing group is used to serve a grouping construct at the beginning, "${BASH_REMATCH[2]}" holds the required value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM