OILS / spec / var-op-patsub.test.sh View on Github | oilshell.org

402 lines, 181 significant
1# Test ${x/pat*/replace}
2# TODO: can add $BUSYBOX_ASH
3
4## oils_failures_allowed: 2
5## compare_shells: bash mksh zsh
6
7#### Pattern replacement
8v=abcde
9echo ${v/c*/XX}
10## stdout: abXX
11
12#### Pattern replacement on unset variable
13echo -${v/x/y}-
14echo status=$?
15set -o nounset # make sure this fails
16echo -${v/x/y}-
17## STDOUT:
18--
19status=0
20## BUG mksh STDOUT:
21# patsub disrespects nounset!
22--
23status=0
24--
25## status: 1
26## OK ash status: 2
27## BUG mksh status: 0
28
29#### Global Pattern replacement with /
30s=xx_xx_xx
31echo ${s/xx?/yy_} ${s//xx?/yy_}
32## stdout: yy_xx_xx yy_yy_xx
33
34#### Left Anchored Pattern replacement with #
35s=xx_xx_xx
36echo ${s/?xx/_yy} ${s/#?xx/_yy}
37## stdout: xx_yy_xx xx_xx_xx
38
39#### Right Anchored Pattern replacement with %
40s=xx_xx_xx
41echo ${s/?xx/_yy} ${s/%?xx/_yy}
42## STDOUT:
43xx_yy_xx xx_xx_yy
44## END
45## BUG ash STDOUT:
46xx_yy_xx xx_xx_xx
47## END
48
49#### Replace fixed strings
50s=xx_xx
51echo ${s/xx/yy} ${s//xx/yy} ${s/#xx/yy} ${s/%xx/yy}
52## STDOUT:
53yy_xx yy_yy yy_xx xx_yy
54## END
55## BUG ash STDOUT:
56yy_xx yy_yy xx_xx xx_xx
57## END
58
59#### Replace is longest match
60# If it were shortest, then you would just replace the first <html>
61s='begin <html></html> end'
62echo ${s/<*>/[]}
63## stdout: begin [] end
64
65#### Replace char class
66s=xx_xx_xx
67echo ${s//[[:alpha:]]/y} ${s//[^[:alpha:]]/-}
68## stdout: yy_yy_yy xx-xx-xx
69## N-I mksh stdout: xx_xx_xx xx_xx_xx
70
71#### Replace hard glob
72s='aa*bb+cc'
73echo ${s//\**+/__} # Literal *, then any sequence of characters, then literal +
74## stdout: aa__cc
75
76#### ${v/} is empty search and replacement
77v=abcde
78echo -${v/}-
79echo status=$?
80## status: 0
81## STDOUT:
82-abcde-
83status=0
84## END
85## BUG ash STDOUT:
86-abcde -
87status=0
88## END
89
90#### ${v//} is empty search and replacement
91v='a/b/c'
92echo -${v//}-
93echo status=$?
94## status: 0
95## STDOUT:
96-a/b/c-
97status=0
98## END
99## BUG ash STDOUT:
100-a/b/c -
101status=0
102## END
103
104#### Confusing unquoted slash matches bash (and ash)
105x='/_/'
106echo ${x////c}
107
108echo ${x//'/'/c}
109
110## STDOUT:
111c_c
112c_c
113## END
114## BUG mksh STDOUT:
115/_/
116c_c
117## END
118## BUG zsh STDOUT:
119/c//c_/c/
120/_/
121## END
122## BUG ash STDOUT:
123c_c
124/_/ /c
125## END
126
127#### Synthesized ${x///} bug (similar to above)
128
129# found via test/parse-errors.sh
130
131x='slash / brace } hi'
132echo 'ambiguous:' ${x///}
133
134echo 'quoted: ' ${x//'/'}
135
136# Wow we have all combination here -- TERRIBLE
137
138## STDOUT:
139ambiguous: slash brace } hi
140quoted: slash brace } hi
141## END
142## BUG mksh STDOUT:
143ambiguous: slash / brace } hi
144quoted: slash brace } hi
145## END
146## BUG zsh STDOUT:
147ambiguous: slash / brace } hi
148quoted: slash / brace } hi
149## END
150## BUG ash STDOUT:
151ambiguous: slash brace } hi
152quoted: slash / brace } hi
153## END
154
155
156#### ${v/a} is the same as ${v/a/} -- no replacement string
157v='aabb'
158echo ${v/a}
159echo status=$?
160## STDOUT:
161abb
162status=0
163## END
164
165#### Replacement with special chars (bug fix)
166v=xx
167echo ${v/x/"?"}
168## stdout: ?x
169
170#### Replace backslash
171v='[\f]'
172x='\f'
173echo ${v/"$x"/_}
174
175# mksh and zsh differ on this case, but this is consistent with the fact that
176# \f as a glob means 'f', not '\f'. TODO: Warn that it's a bad glob?
177# The canonical form is 'f'.
178echo ${v/$x/_}
179
180echo ${v/\f/_}
181echo ${v/\\f/_}
182## STDOUT:
183[_]
184[\_]
185[\_]
186[_]
187## END
188## BUG mksh/zsh STDOUT:
189[_]
190[_]
191[\_]
192[_]
193## END
194
195#### Replace right ]
196v='--]--'
197x=']'
198echo ${v/"$x"/_}
199echo ${v/$x/_}
200## STDOUT:
201--_--
202--_--
203## END
204
205#### Substitute glob characters in pattern, quoted and unquoted
206
207# INFINITE LOOP in ash!
208case $SH in ash) exit ;; esac
209
210g='*'
211v='a*b'
212echo ${v//"$g"/-}
213echo ${v//$g/-}
214## STDOUT:
215a-b
216-
217## END
218## BUG zsh STDOUT:
219a-b
220a-b
221## END
222
223#### Substitute one unicode character (UTF-8)
224export LANG='en_US.UTF-8'
225
226s='_μ_ and _μ_'
227
228# ? should match one char
229
230echo ${s//_?_/foo} # all
231echo ${s/#_?_/foo} # left
232echo ${s/%_?_/foo} # right
233
234## STDOUT:
235foo and foo
236foo and _μ_
237_μ_ and foo
238## END
239## BUG mksh STDOUT:
240_μ_ and _μ_
241_μ_ and _μ_
242_μ_ and _μ_
243## END
244
245#### Can't substitute one unicode character when LC_ALL=C
246export LC_ALL='C'
247
248s='_μ_ and _μ_'
249
250# ? should match one char
251
252echo ${s//_?_/foo} # all
253echo ${s/#_?_/foo} # left
254echo ${s/%_?_/foo} # right
255
256## STDOUT:
257_μ_ and _μ_
258_μ_ and _μ_
259_μ_ and _μ_
260## END
261
262#### ${x/^} regression
263x=abc
264echo ${x/^}
265echo ${x/!}
266
267y=^^^
268echo ${y/^}
269echo ${y/!}
270
271z=!!!
272echo ${z/^}
273echo ${z/!}
274
275s=a^b!c
276echo ${s/a^}
277echo ${s/b!}
278
279## STDOUT:
280abc
281abc
282^^
283^^^
284!!!
285!!
286b!c
287a^c
288## END
289
290#### \(\) in pattern (regression)
291
292# Not extended globs
293x='foo()'
294echo 1 ${x//*\(\)/z}
295echo 2 ${x//*\(\)/z}
296echo 3 ${x//\(\)/z}
297echo 4 ${x//*\(\)/z}
298
299## STDOUT:
3001 z
3012 z
3023 fooz
3034 z
304## END
305
306#### patsub with single quotes and hyphen in character class (regression)
307
308# from Crestwave's bf.bash
309
310program='^++--hello.,world<>[]'
311program=${program//[^'><+-.,[]']}
312echo $program
313## STDOUT:
314++--.,<>[]
315## END
316## BUG mksh STDOUT:
317helloworld
318## END
319
320#### patsub with [^]]
321
322# This is a PARSING divergence. In Oil we match [], rather than using POSIX
323# rules!
324
325pat='[^]]'
326s='ab^cd^'
327echo ${s//$pat/z}
328## STDOUT:
329ab^cd^
330## END
331
332#### [a-z] Invalid range end is syntax error
333x=fooz
334pat='[z-a]' # Invalid range. Other shells don't catch it!
335#pat='[a-y]'
336echo ${x//$pat}
337echo status=$?
338## stdout-json: ""
339## status: 1
340## OK bash/mksh/zsh/ash STDOUT:
341fooz
342status=0
343## END
344## OK bash/mksh/zsh/ash status: 0
345
346
347#### Pattern is empty $foo$bar -- regression for infinite loop
348
349x=-foo-
350
351echo ${x//$foo$bar/bar}
352
353## STDOUT:
354-foo-
355## END
356
357# feels like memory unsafety in ZSH
358## BUG zsh STDOUT:
359bar-barfbarobarobar-
360## END
361
362#### Chromium from http://www.oilshell.org/blog/2016/11/07.html
363
364case $SH in zsh) exit ;; esac
365
366HOST_PATH=/foo/bar/baz
367echo ${HOST_PATH////\\/}
368
369# The way bash parses it
370echo ${HOST_PATH//'/'/\\/}
371
372## STDOUT:
373\/foo\/bar\/baz
374\/foo\/bar\/baz
375## END
376
377# zsh has crazy bugs
378## BUG zsh stdout-json: ""
379
380## BUG mksh STDOUT:
381/foo/bar/baz
382\/foo\/bar\/baz
383## END
384
385
386#### ${x//~homedir/}
387
388path=~/git/oilshell
389
390# ~ expansion occurs
391#echo path=$path
392
393echo ${path//~/z}
394
395echo ${path/~/z}
396
397## STDOUT:
398z/git/oilshell
399z/git/oilshell
400## END
401
402