In writing a script for the ZSH shell, I wanted to extract some bits from a string. I looked for a regex solution, using capture groups. I could not figure out how to do it with sed
but I found that the [[ ]]
format of the test
command allows this with the =~
operator. If the test returns true, values are stored in a $match
array and can be accessed like $match[1]
and so on.
In my use case, I was trying to improve on ZSH’s run-help
function. Some of its results say things like:
See the section `ZLE BUILTINS' in zshzle(1).
Why not just show that section of that manpage directly? So I wanted to check if the output was of that format, and if so, extract the section and manpage bits and use them to show the information I would be looking for. After a bit of experimenting I ended up with the regex test looking like:
[[ "$var" =~ "See the section \`([^']+)' in ([^\(]+)" ]]
and the capture groups were accessed like:
man -P "${PAGER:-less} -Ip '${match[1]}'" "$match[2]"
The overall script I created using it ended up something like:
autoload -Uz run-help
function h(){
if [ -z "$HELPDIR" ]; then
local HELPDIR="/usr/share/zsh/${ZSH_VERSION}/help"
fi
s="$@"
out=`\run-help "$s" 2> /dev/null`
if [[ "$out" =~ "See the section \`([^']+)' in ([^\(]+)" ]]; then
man -P "${PAGER:-less} -Ip '${match[1]}'" "$match[2]"
else
\run-help $s
fi
}
The =~
matching also works similarly in Bash, but there the array is called $BASH_REMATCH
instead of $match
.