1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-13 11:21:13 +02:00

27604: substitution using regular expressions

This commit is contained in:
Peter Stephenson 2010-01-18 12:47:09 +00:00
parent 8890e6e19f
commit c508c6e368
4 changed files with 78 additions and 11 deletions

View file

@ -1570,14 +1570,14 @@ tindex(replace-string-again)
tindex(replace-pattern) tindex(replace-pattern)
xitem(tt(replace-string), tt(replace-pattern)) xitem(tt(replace-string), tt(replace-pattern))
item(tt(replace-string-again), tt(replace-pattern-again))( item(tt(replace-string-again), tt(replace-pattern-again))(
The function tt(replace-string) implements two widgets. The function tt(replace-string) implements three widgets.
If defined under the same name as the function, it prompts for two If defined under the same name as the function, it prompts for two
strings; the first (source) string will be replaced by the second strings; the first (source) string will be replaced by the second
everywhere it occurs in the line editing buffer. everywhere it occurs in the line editing buffer.
If the widget name contains the word `tt(pattern)', for example by If the widget name contains the word `tt(pattern)', for example by
defining the widget using the command `tt(zle -N replace-pattern defining the widget using the command `tt(zle -N replace-pattern
replace-string)', then the replacement is done by pattern matching. All replace-string)', then the matching is performed using zsh patterns. All
zsh extended globbing patterns can be used in the source string; note zsh extended globbing patterns can be used in the source string; note
that unlike filename generation the pattern does not need to match an that unlike filename generation the pattern does not need to match an
entire word, nor do glob qualifiers have any effect. In addition, the entire word, nor do glob qualifiers have any effect. In addition, the
@ -1588,6 +1588,12 @@ replaced by the var(N)th parenthesised expression matched. The form
`tt(\{)var(N)tt(})' may be used to protect the digit from following `tt(\{)var(N)tt(})' may be used to protect the digit from following
digits. digits.
If the widget instead contains the word `tt(regex)' (or `tt(regexp)'),
then the matching is performed using regular expressions, respecting
the setting of the option tt(RE_MATCH_PCRE) (see the description of the
function tt(regexp-replace) below). The facilities described
for pattern matching are also available.
By default the previous source or replacement string will not be offered By default the previous source or replacement string will not be offered
for editing. However, this feature can be activated by setting the style for editing. However, this feature can be activated by setting the style
tt(edit-previous) in the context tt(:zle:)var(widget) (for example, tt(edit-previous) in the context tt(:zle:)var(widget) (for example,
@ -1595,12 +1601,12 @@ tt(:zle:replace-string)) to tt(true). In addition, a positive
numeric argument forces the previous values to be offered, a negative or numeric argument forces the previous values to be offered, a negative or
zero argument forces them not to be. zero argument forces them not to be.
The function tt(replace-string-again) can be used to repeat the The function tt(replace-string-again) can be used to repeat the previous
previous replacement; no prompting is done. As with tt(replace-string), if replacement; no prompting is done. As with tt(replace-string), if the name
the name of the widget contains the word `tt(pattern)', pattern matching of the widget contains the word `tt(pattern)' or `tt(regex)', pattern or
is performed, else a literal string replacement. Note that the regular expression matching is performed, else a literal string
previous source and replacement text are the same whether pattern or string replacement. Note that the previous source and replacement text are the
matching is used. same whether pattern, regular expression or string matching is used.
For example, starting from the line: For example, starting from the line:
@ -2574,6 +2580,25 @@ the context prefix `tt(:completion:nslookup)'.
See also the tt(pager), tt(prompt) and tt(rprompt) styles below. See also the tt(pager), tt(prompt) and tt(rprompt) styles below.
) )
findex(regexp-replace)
item(tt(regexp-replace) var(var) var(regexp) var(replace))(
Use regular expressions to perform a global search and replace operation
on a variable. If the option tt(RE_MATCH_PCRE) is not set, POSIX
extended regular expressions are used, else Perl-compatible regular
expressions (this requires the shell to be linked against the tt(pcre)
library).
var(var) is the name of the variable containing the string to be matched.
The variable will be modified directly by the function. The
variables tt(MATCH), tt(MBEGIN), tt(MEND), tt(match), tt(mbegin), tt(mend)
should be avoided as these are used by the regular expression code.
var(regexp) is the regular expression to match against the string.
var(replace) is the replacement text. This can contain parameter, command
and arithmetic expressions which will be replaced: in particular, a
reference to tt($MATCH) will be replaced by the text matched by the pattern.
)
findex(run-help) findex(run-help)
item(tt(run-help) var(cmd))( item(tt(run-help) var(cmd))(
This function is designed to be invoked by the tt(run-help) ZLE widget, This function is designed to be invoked by the tt(run-help) ZLE widget,

View file

@ -10,6 +10,7 @@ is-at-least
mere mere
nslookup nslookup
promptnl promptnl
regexp-replace
relative relative
run-help run-help
run-help-git run-help-git

View file

@ -0,0 +1,35 @@
# Replace all occurrences of a regular expression in a variable. The
# variable is modified directly. Respects the setting of the
# option RE_MATCH_PCRE.
#
# First argument: *name* (not contents) of variable.
# Second argument: regular expression
# Third argument: replacement string. This can contain all forms of
# $ and backtick substitutions; in particular, $MATCH will be replaced
# by the portion of the string matched by the regular expression.
integer pcre
[[ -o re_match_pcre ]] && pcre=1
emulate -L zsh
(( pcre )) && setopt re_match_pcre
# $4 is the string to be matched
4=${(P)1}
# $5 is the final string
5=
local MATCH MBEGIN MEND
local -a match mbegin mend
while [[ -n $4 ]]; do
if [[ $4 =~ $2 ]]; then
5+=${4[1,MBEGIN-1]}${(e)3}
4=${4[MEND+1,-1]}
else
break
fi
done
5+=$4
eval ${1}=${(q)5}

View file

@ -13,7 +13,7 @@ if [[ -z $_replace_string_src ]]; then
return 1 return 1
fi fi
if [[ $curwidget = *pattern* ]]; then if [[ $curwidget = *(pattern|regex)* ]]; then
local rep2 local rep2
# The following horror is so that an & preceded by an even # The following horror is so that an & preceded by an even
# number of backslashes is active, without stripping backslashes, # number of backslashes is active, without stripping backslashes,
@ -38,8 +38,14 @@ if [[ $curwidget = *pattern* ]]; then
rep=${match[5]} rep=${match[5]}
done done
rep2+=$rep rep2+=$rep
if [[ $curwidget = *regex* ]]; then
autoload -U regexp-replace
regexp-replace LBUFFER $_replace_string_src $rep2
regexp-replace RBUFFER $_replace_string_src $rep2
else
LBUFFER=${LBUFFER//(#bm)$~_replace_string_src/${(e)rep2}} LBUFFER=${LBUFFER//(#bm)$~_replace_string_src/${(e)rep2}}
RBUFFER=${RBUFFER//(#bm)$~_replace_string_src/${(e)rep2}} RBUFFER=${RBUFFER//(#bm)$~_replace_string_src/${(e)rep2}}
fi
else else
LBUFFER=${LBUFFER//$_replace_string_src/$_replace_string_rep} LBUFFER=${LBUFFER//$_replace_string_src/$_replace_string_rep}
RBUFFER=${RBUFFER//$_replace_string_src/$_replace_string_rep} RBUFFER=${RBUFFER//$_replace_string_src/$_replace_string_rep}