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 #### ${v/a} is the same as ${v/a/} -- no replacement string
88 v='aabb'
89 echo ${v/a}
90 echo status=$?
91 ## STDOUT:
92 abb
93 status=0
94 ## END
95
96 #### Replacement with special chars (bug fix)
97 v=xx
98 echo ${v/x/"?"}
99 ## stdout: ?x
100
101 #### Replace backslash
102 v='[\f]'
103 x='\f'
104 echo ${v/"$x"/_}
105
106 # mksh and zsh differ on this case, but this is consistent with the fact that
107 # \f as a glob means 'f', not '\f'. TODO: Warn that it's a bad glob?
108 # The canonical form is 'f'.
109 echo ${v/$x/_}
110
111 echo ${v/\f/_}
112 echo ${v/\\f/_}
113 ## STDOUT:
114 [_]
115 [\_]
116 [\_]
117 [_]
118 ## END
119 ## BUG mksh/zsh STDOUT:
120 [_]
121 [_]
122 [\_]
123 [_]
124 ## END
125
126 #### Replace right ]
127 v='--]--'
128 x=']'
129 echo ${v/"$x"/_}
130 echo ${v/$x/_}
131 ## STDOUT:
132 --_--
133 --_--
134 ## END
135
136 #### Substitute glob characters in pattern, quoted and unquoted
137 g='*'
138 v='a*b'
139 echo ${v//"$g"/-}
140 echo ${v//$g/-}
141 ## STDOUT:
142 a-b
143 -
144 ## END
145 ## BUG zsh STDOUT:
146 a-b
147 a-b
148 ## END
149
150 #### Substitute one unicode character (UTF-8)
151 export LANG='en_US.UTF-8'
152
153 s='_μ_ and _μ_'
154
155 # ? should match one char
156
157 echo ${s//_?_/foo} # all
158 echo ${s/#_?_/foo} # left
159 echo ${s/%_?_/foo} # right
160
161 ## STDOUT:
162 foo and foo
163 foo and _μ_
164 _μ_ and foo
165 ## END
166 ## BUG mksh STDOUT:
167 _μ_ and _μ_
168 _μ_ and _μ_
169 _μ_ and _μ_
170 ## END
171
172 #### Can't substitute one unicode character when LANG=C
173 export LANG='C'
174 export LC_CTYPE='C'
175
176 s='_μ_ and _μ_'
177
178 # ? should match one char
179
180 echo ${s//_?_/foo} # all
181 echo ${s/#_?_/foo} # left
182 echo ${s/%_?_/foo} # right
183
184 ## STDOUT:
185 _μ_ and _μ_
186 _μ_ and _μ_
187 _μ_ and _μ_
188 ## END