Bash regex

I have a regex pattern that should match in several places in a string. I want all matching groups to be in the same array and then print each element.

So, I tried this:

#!/bin/bash f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' regex=$'\n\t(.+?)\\s+Disk' if [[ $f =~ $regex ]] then for match in "${BASH_REMATCH[@]}" do echo "New match: $match" done else echo "No matches" fi 

Result:

 New match: Share1 Disk Share2 Disk New match: Share1 Disk Share2 

Expected Result:

 New match: Share1 New match: Share2 

I think this will not work, because mine .+? matches greedy. So I looked at how this can be done with bash regex. But everyone seems to suggest using grep with the perl regex.

But, of course, there must be a different way. I was thinking maybe something like [^\\s]+ .. But the solution for this was:

 New match: Share1 Disk New match: Share1 

... any ideas?

+7
bash regex regex-greedy
source share
1 answer

There are a couple of issues here. First, the first element of BASH_REMATCH is the entire line that matches the pattern, not the capture group, so you want to use ${BASH_REMATCH[@]:1} to get the things that were in the capture groups.

However, bash regex does not support repeating matches multiple times per line, so bash is probably not suitable for this task. However, since things are in their own lines, you can try to use them to separate things and apply a pattern to each line, for example:

 f=$'\n\tShare1 Disk\n\tShare2 Disk\n\tPrnt1 Printer' regex=$'\t(\S+?)\\s+Disk' while IFS=$'\n' read -r line; do if [[ $line =~ $regex ]] then printf 'New match: %s\n' "${BASH_REMATCH[@]:1}" else echo "No matches" fi done <<<"$f" 
+5
source share

All Articles