1 |
#!/bin/bash |
2 |
# |
3 |
# Test ${x/pat*/replace} |
4 |
|
5 |
#### Pattern replacement |
6 |
v=abcde |
7 |
echo ${v/c*/XX} |
8 |
## stdout: abXX |
9 |
|
10 |
#### Pattern replacement on unset variable |
11 |
echo -${v/x/y}- |
12 |
echo status=$? |
13 |
set -o nounset # make sure this fails |
14 |
echo -${v/x/y}- |
15 |
## STDOUT: |
16 |
-- |
17 |
status=0 |
18 |
## BUG mksh STDOUT: |
19 |
# patsub disrespects nounset! |
20 |
-- |
21 |
status=0 |
22 |
-- |
23 |
## status: 1 |
24 |
## BUG mksh status: 0 |
25 |
|
26 |
#### Global Pattern replacement with / |
27 |
s=xx_xx_xx |
28 |
echo ${s/xx?/yy_} ${s//xx?/yy_} |
29 |
## stdout: yy_xx_xx yy_yy_xx |
30 |
|
31 |
#### Left Anchored Pattern replacement with # |
32 |
s=xx_xx_xx |
33 |
echo ${s/?xx/_yy} ${s/#?xx/_yy} |
34 |
## stdout: xx_yy_xx xx_xx_xx |
35 |
|
36 |
#### Right Anchored Pattern replacement with % |
37 |
s=xx_xx_xx |
38 |
echo ${s/?xx/_yy} ${s/%?xx/_yy} |
39 |
## stdout: xx_yy_xx xx_xx_yy |
40 |
|
41 |
#### Replace fixed strings |
42 |
s=xx_xx |
43 |
echo ${s/xx/yy} ${s//xx/yy} ${s/#xx/yy} ${s/%xx/yy} |
44 |
## stdout: yy_xx yy_yy yy_xx xx_yy |
45 |
|
46 |
#### Replace is longest match |
47 |
# If it were shortest, then you would just replace the first <html> |
48 |
s='begin <html></html> end' |
49 |
echo ${s/<*>/[]} |
50 |
## stdout: begin [] end |
51 |
|
52 |
#### Replace char class |
53 |
s=xx_xx_xx |
54 |
echo ${s//[[:alpha:]]/y} ${s//[^[:alpha:]]/-} |
55 |
## stdout: yy_yy_yy xx-xx-xx |
56 |
## N-I mksh stdout: xx_xx_xx xx_xx_xx |
57 |
|
58 |
#### Replace hard glob |
59 |
s='aa*bb+cc' |
60 |
echo ${s//\**+/__} # Literal *, then any sequence of characters, then literal + |
61 |
## stdout: aa__cc |
62 |
|
63 |
#### Pattern replacement ${v/} is not valid |
64 |
v=abcde |
65 |
echo -${v/}- |
66 |
echo status=$? |
67 |
## status: 2 |
68 |
## stdout-json: "" |
69 |
## BUG bash/mksh/zsh status: 0 |
70 |
## BUG bash/mksh/zsh STDOUT: |
71 |
-abcde- |
72 |
status=0 |
73 |
## END |
74 |
|
75 |
#### Pattern replacement ${v//} is not valid |
76 |
v='a/b/c' |
77 |
echo -${v//}- |
78 |
echo status=$? |
79 |
## status: 2 |
80 |
## stdout-json: "" |
81 |
## BUG bash/mksh/zsh status: 0 |
82 |
## BUG bash/mksh/zsh STDOUT: |
83 |
-a/b/c- |
84 |
status=0 |
85 |
## END |
86 |
|
87 |
#### Confusing unquoted slash matches bash (and ash) |
88 |
x='/_/' |
89 |
echo ${x////c} |
90 |
echo ${x//'/'/c} |
91 |
## STDOUT: |
92 |
c_c |
93 |
c_c |
94 |
## END |
95 |
## BUG mksh/yash STDOUT: |
96 |
/_/ |
97 |
c_c |
98 |
## END |
99 |
## BUG zsh STDOUT: |
100 |
/c//c_/c/ |
101 |
/_/ |
102 |
## END |
103 |
## BUG ash STDOUT: |
104 |
c_c |
105 |
/_/ |
106 |
## END |
107 |
|
108 |
#### ${v/a} is the same as ${v/a/} -- no replacement string |
109 |
v='aabb' |
110 |
echo ${v/a} |
111 |
echo status=$? |
112 |
## STDOUT: |
113 |
abb |
114 |
status=0 |
115 |
## END |
116 |
|
117 |
#### Replacement with special chars (bug fix) |
118 |
v=xx |
119 |
echo ${v/x/"?"} |
120 |
## stdout: ?x |
121 |
|
122 |
#### Replace backslash |
123 |
v='[\f]' |
124 |
x='\f' |
125 |
echo ${v/"$x"/_} |
126 |
|
127 |
# mksh and zsh differ on this case, but this is consistent with the fact that |
128 |
# \f as a glob means 'f', not '\f'. TODO: Warn that it's a bad glob? |
129 |
# The canonical form is 'f'. |
130 |
echo ${v/$x/_} |
131 |
|
132 |
echo ${v/\f/_} |
133 |
echo ${v/\\f/_} |
134 |
## STDOUT: |
135 |
[_] |
136 |
[\_] |
137 |
[\_] |
138 |
[_] |
139 |
## END |
140 |
## BUG mksh/zsh STDOUT: |
141 |
[_] |
142 |
[_] |
143 |
[\_] |
144 |
[_] |
145 |
## END |
146 |
|
147 |
#### Replace right ] |
148 |
v='--]--' |
149 |
x=']' |
150 |
echo ${v/"$x"/_} |
151 |
echo ${v/$x/_} |
152 |
## STDOUT: |
153 |
--_-- |
154 |
--_-- |
155 |
## END |
156 |
|
157 |
#### Substitute glob characters in pattern, quoted and unquoted |
158 |
g='*' |
159 |
v='a*b' |
160 |
echo ${v//"$g"/-} |
161 |
echo ${v//$g/-} |
162 |
## STDOUT: |
163 |
a-b |
164 |
- |
165 |
## END |
166 |
## BUG zsh STDOUT: |
167 |
a-b |
168 |
a-b |
169 |
## END |
170 |
|
171 |
#### Substitute one unicode character (UTF-8) |
172 |
export LANG='en_US.UTF-8' |
173 |
|
174 |
s='_μ_ and _μ_' |
175 |
|
176 |
# ? should match one char |
177 |
|
178 |
echo ${s//_?_/foo} # all |
179 |
echo ${s/#_?_/foo} # left |
180 |
echo ${s/%_?_/foo} # right |
181 |
|
182 |
## STDOUT: |
183 |
foo and foo |
184 |
foo and _μ_ |
185 |
_μ_ and foo |
186 |
## END |
187 |
## BUG mksh STDOUT: |
188 |
_μ_ and _μ_ |
189 |
_μ_ and _μ_ |
190 |
_μ_ and _μ_ |
191 |
## END |
192 |
|
193 |
#### Can't substitute one unicode character when LANG=C |
194 |
export LANG='C' |
195 |
export LC_CTYPE='C' |
196 |
|
197 |
s='_μ_ and _μ_' |
198 |
|
199 |
# ? should match one char |
200 |
|
201 |
echo ${s//_?_/foo} # all |
202 |
echo ${s/#_?_/foo} # left |
203 |
echo ${s/%_?_/foo} # right |
204 |
|
205 |
## STDOUT: |
206 |
_μ_ and _μ_ |
207 |
_μ_ and _μ_ |
208 |
_μ_ and _μ_ |
209 |
## END |
210 |
|
211 |
#### ${x/^} regression |
212 |
x=abc |
213 |
echo ${x/^} |
214 |
echo ${x/!} |
215 |
|
216 |
y=^^^ |
217 |
echo ${y/^} |
218 |
echo ${y/!} |
219 |
|
220 |
z=!!! |
221 |
echo ${z/^} |
222 |
echo ${z/!} |
223 |
|
224 |
s=a^b!c |
225 |
echo ${s/a^} |
226 |
echo ${s/b!} |
227 |
|
228 |
## STDOUT: |
229 |
abc |
230 |
abc |
231 |
^^ |
232 |
^^^ |
233 |
!!! |
234 |
!! |
235 |
b!c |
236 |
a^c |
237 |
## END |
238 |
|
239 |
#### \(\) in pattern (regression) |
240 |
|
241 |
# Not extended globs |
242 |
x='foo()' |
243 |
echo 1 ${x//*\(\)/z} |
244 |
echo 2 ${x//*\(\)/z} |
245 |
echo 3 ${x//\(\)/z} |
246 |
echo 4 ${x//*\(\)/z} |
247 |
|
248 |
## STDOUT: |
249 |
1 z |
250 |
2 z |
251 |
3 fooz |
252 |
4 z |
253 |
## END |
254 |
|
255 |
|
256 |
#### Extended globs! (not supported in Oil) |
257 |
shopt -s extglob |
258 |
|
259 |
x='foo()' |
260 |
echo ext ${x//*(foo|bar)/z} |
261 |
echo ext "${x//*(foo|bar)/z}" |
262 |
|
263 |
## STDOUT: |
264 |
ext z() |
265 |
ext z() |
266 |
## END |
267 |
|
268 |
# I don't get what bash is doing here! |
269 |
## BUG bash STDOUT: |
270 |
ext zz(z) |
271 |
ext zz(z) |
272 |
## END |
273 |
|
274 |
# GlobToERE doesn't support extended globs! |
275 |
|
276 |
## N-I osh STDOUT: |
277 |
ext foo() |
278 |
ext foo() |
279 |
## END |
280 |
|
281 |
#### patsub with single quotes and hyphen in character class (regression) |
282 |
|
283 |
# from Crestwave's bf.bash |
284 |
|
285 |
program='^++--hello.,world<>[]' |
286 |
program=${program//[^'><+-.,[]']} |
287 |
echo $program |
288 |
## STDOUT: |
289 |
++--.,<>[] |
290 |
## END |
291 |
## BUG mksh STDOUT: |
292 |
helloworld |
293 |
## END |
294 |
|
295 |
#### patsub with [^]] |
296 |
|
297 |
# This is a PARSING divergence. In Oil we match [], rather than using POSIX |
298 |
# rules! |
299 |
|
300 |
pat='[^]]' |
301 |
s='ab^cd^' |
302 |
echo ${s//$pat/z} |
303 |
## STDOUT: |
304 |
ab^cd^ |
305 |
## END |
306 |
|
307 |
#### patsub syntax error |
308 |
x=fooz |
309 |
pat='[z-a]' # Invalid range. Other shells don't catch it! |
310 |
#pat='[a-y]' |
311 |
echo ${x//$pat} |
312 |
echo status=$? |
313 |
## stdout-json: "" |
314 |
## status: 1 |
315 |
## OK bash/mksh/zsh STDOUT: |
316 |
fooz |
317 |
status=0 |
318 |
## END |
319 |
## OK bash/mksh/zsh status: 0 |