zsh-workers
 help / color / mirror / code / Atom feed
0e3deed4f942260d1fdfa1d5e2ccbc724ae4a53d blob 2711 bytes (raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 
# Replace all occurrences of a regular expression in a scalar variable.
# The variable is modified directly.  Respects the setting of the option
# RE_MATCH_PCRE, but otherwise sets the zsh emulation mode.
#
# Arguments:
#
# 1. *name* (not contents) of variable or more generally any lvalue;
#    expected to be scalar.
#
# 2. regular expression
#
# 3. 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. Parsing errors are fatal to the shell process.

if (( $# < 2 || $# > 3 )); then
  setopt localoptions functionargzero
  print -ru2 "Usage: $0 <varname> <regexp> [<replacement>]"
  return 2
fi

# ensure variable exists in the caller's scope before referencing it
# to make sure we don't end up referencing one of our own.
typeset -g -- "$1" || return 2
typeset -nu -- var=$1 || return 2

local -i use_pcre=0
[[ -o re_match_pcre ]] && use_pcre=1

emulate -L zsh

local regexp=$2 replacement=$3 result MATCH MBEGIN MEND
local -a match mbegin mend

if (( use_pcre )); then
  # if using pcre, we're using pcre_match and a running offset
  # That's needed for ^, \A, \b, and look-behind operators to work
  # properly.

  zmodload zsh/pcre || return 2
  pcre_compile -- "$regexp" && pcre_study || return 2

  local -i offset=0 start stop
  local new ZPCRE_OP
  local -a finds

  while pcre_match -b -n $offset -- "$var"; do
    # we need to perform the evaluation in a scalar assignment so that
    # if it generates an array, the elements are converted to string (by
    # joining with the first chararacter of $IFS as usual)
    new=${(Xe)replacement}

    finds+=( ${(s[ ])ZPCRE_OP} "$new" )

    # for 0-width matches, increase offset by 1 to avoid
    # infinite loop
    (( offset = finds[-2] + (finds[-3] == finds[-2]) ))
  done

  (( $#finds )) || return # no match

  unsetopt multibyte

  offset=1
  for start stop new in "$finds[@]"; do
    result+=${var[offset,start]}$new
    (( offset = stop + 1 ))
  done
  result+=${var[offset,-1]}

else # no PCRE

  # in ERE, we can't use an offset so ^, (and \<, \b, \B, [[:<:]] where
  # available) won't work properly.
  local subject=$var
  local -i ok
  while [[ $subject =~ $regexp ]]; do
    # append initial part and substituted match
    result+=$subject[1,MBEGIN-1]${(Xe)replacement}
    # truncate remaining string
    if (( MEND < MBEGIN )); then
      # zero-width match, skip one character for the next match
      (( MEND++ ))
      result+=$subject[MBEGIN]
    fi
    subject=$subject[MEND+1,-1]
    ok=1
    [[ -n $subject ]] && break
  done
  (( ok )) || return
  result+=$subject
fi

var=$result
debug log:

solving 0e3deed4f ...
found 0e3deed4f in https://inbox.vuxu.org/zsh-workers/20240308153050.u63fqtcjyr2yewye@chazelas.org/
found d4408f0f7 in https://git.vuxu.org/mirror/zsh/
preparing index
index prepared:
100644 d4408f0f78cdfbf6882ffed8869e7a9a67324602	Functions/Misc/regexp-replace

applying [1/1] https://inbox.vuxu.org/zsh-workers/20240308153050.u63fqtcjyr2yewye@chazelas.org/
diff --git a/Functions/Misc/regexp-replace b/Functions/Misc/regexp-replace
index d4408f0f7..0e3deed4f 100644

Checking patch Functions/Misc/regexp-replace...
Applied patch Functions/Misc/regexp-replace cleanly.

index at:
100644 0e3deed4f942260d1fdfa1d5e2ccbc724ae4a53d	Functions/Misc/regexp-replace

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).