ZSH Gem #18: Regexp search and replace on parameters
In ZSH you can easily perform regexp search and replace operations on shell parameters. The only function you need for this is regexp-replace
.
Regexp search and replace can be very useful when writing shell scripts which need to process input data, directory names, process trees etc. You assign the string which you need to work on to a parameter and then run the replace function on it. But before you can do anything, you need to load the function first:
autoload -U regexp-replace
The syntax of regexp-replace
is as follows:
regexp-replace VARNAME REGEXP REPLACE
where VARNAME
is the name of the variable, REGEXP
the regular expression and REPLACE
the replace string.
As an example of how to use regexp-replace
let us replace all occurrences of /foo/bar
in the $PATH
variable. So let's add that first of all:
PATH="$PATH:/foo/bar"
echo $PATH
There we have it. Now let us remove that entry again:
regexp-replace PATH ':/foo/bar' ''
That will replace our newly added string with an empty string. Of course this was a very basic pattern. But we can use the full POSIX extended regexp syntax and if we enable the option RE_MATCH_PCRE
setopt re_match_pcre
we can even use full Perl compatible regular expressions (provided ZSH was built with PCRE support). Let's do that and replace all entries starting with /usr/
with foo
:
regexp-replace PATH '(^|:)/usr/[^:]*' ':foo'
Unfortunately there is no direct way to use back references for each parenthesis expression in the replace pattern, but there are at least some special variables: $MATCH
contains the matched portion, $1
contains the variable name and $2
contains the pattern. For instance to append /subdir
to the paths starting with /usr
instead of replacing the whole thing, we could write
regexp-replace PATH '(^|:)/usr/[^:]*' '$MATCH/subdir'
Mind the single quotes! $MATCH
is not an actual shell parameter but rather a placeholder which is replaced by the regexp-replace
function. If you would use double quotes or even no quotes, you'd get an empty string (except $MATCH
already has some value assigned to it, but normally that's not what you want anyways). The same applies to $1
and $2
.
regexp-replace
is a nice addition to ZSH's parameter expansion patterns. It's easy to use and in most cases more than sufficient.
Read more about regexp-replace: