1 |
|
2 | #### Remove const suffix
|
3 | v=abcd
|
4 | echo ${v%d} ${v%%cd}
|
5 | ## stdout: abc ab
|
6 |
|
7 | #### Remove const prefix
|
8 | v=abcd
|
9 | echo ${v#a} ${v##ab}
|
10 | ## stdout: bcd cd
|
11 |
|
12 | #### Remove const suffix is vectorized on user array
|
13 | a=(1a 2a 3a)
|
14 | argv.py ${a[@]%a}
|
15 | ## stdout: ['1', '2', '3']
|
16 | ## status: 0
|
17 | ## N-I dash/mksh/ash stdout-json: ""
|
18 | ## N-I dash/ash status: 2
|
19 | ## N-I mksh status: 1
|
20 |
|
21 | #### Remove const suffix is vectorized on $@ array
|
22 | set -- 1a 2a 3a
|
23 | argv.py ${@%a}
|
24 | ## stdout: ['1', '2', '3']
|
25 | ## status: 0
|
26 | ## N-I dash/ash stdout: ['1a', '2a', '3']
|
27 | ## N-I dash/ash status: 0
|
28 | ## N-I mksh stdout-json: ""
|
29 | ## N-I mksh status: 1
|
30 |
|
31 | #### Remove const suffix from undefined
|
32 | echo ${undef%suffix}
|
33 | ## stdout:
|
34 |
|
35 | #### Remove shortest glob suffix
|
36 | v=aabbccdd
|
37 | echo ${v%c*}
|
38 | ## stdout: aabbc
|
39 |
|
40 | #### Remove longest glob suffix
|
41 | v=aabbccdd
|
42 | echo ${v%%c*}
|
43 | ## stdout: aabb
|
44 |
|
45 | #### Remove shortest glob prefix
|
46 | v=aabbccdd
|
47 | echo ${v#*b}
|
48 | ## stdout: bccdd
|
49 |
|
50 | #### Remove longest glob prefix
|
51 | v=aabbccdd
|
52 | echo ${v##*b}
|
53 | ## stdout: ccdd
|
54 |
|
55 | #### Strip char class
|
56 | v=abc
|
57 | echo ${v%[[:alpha:]]}
|
58 | ## stdout: ab
|
59 | ## N-I mksh stdout: abc
|
60 |
|
61 | #### Strip unicode prefix
|
62 | # NOTE: LANG is set to utf-8.
|
63 | v='μ-'
|
64 | echo ${v#?} # ? is a glob that stands for one character
|
65 | echo ${v##?}
|
66 | v='-μ'
|
67 | echo ${v%?} # ? is a glob that stands for one character
|
68 | echo ${v%%?}
|
69 | ## STDOUT:
|
70 | -
|
71 | -
|
72 | -
|
73 | -
|
74 | ## BUG dash/mksh/ash stdout-repr: '\xbc-\n\xbc-\n-\xce\n-\xce\n'
|
75 | ## BUG zsh stdout-repr: '\n\n\n\n'
|
76 |
|
77 | #### Bug fix: Test that you can remove everything with glob
|
78 | s='--x--'
|
79 | argv.py "${s%%-*}" "${s%-*}" "${s#*-}" "${s##*-}"
|
80 | ## STDOUT:
|
81 | ['', '--x-', '-x--', '']
|
82 | ## END
|
83 |
|
84 | #### Test that you can remove everything with const
|
85 | s='abcd'
|
86 | argv.py "${s%%abcd}" "${s%abcd}" "${s#abcd}" "${s##abcd}"
|
87 | # failure case:
|
88 | argv.py "${s%%abcde}" "${s%abcde}" "${s#abcde}" "${s##abcde}"
|
89 | ## STDOUT:
|
90 | ['', '', '', '']
|
91 | ['abcd', 'abcd', 'abcd', 'abcd']
|
92 | ## END
|
93 |
|
94 | #### Prepend using replacement of #
|
95 | # This case was found in Kubernetes and others
|
96 | array=(aa bb '')
|
97 | argv.py ${array[@]/#/prefix-}
|
98 | ## STDOUT:
|
99 | ['prefix-aa', 'prefix-bb', 'prefix-']
|
100 | ## END
|
101 | ## N-I dash/ash status: 2
|
102 | ## N-I dash/ash stdout-json: ""
|
103 | ## N-I mksh status: 1
|
104 | ## N-I mksh stdout-json: ""
|
105 |
|
106 | #### Append using replacement of %
|
107 | array=(aa bb '')
|
108 | argv.py ${array[@]/%/-suffix}
|
109 | ## STDOUT:
|
110 | ['aa-suffix', 'bb-suffix', '-suffix']
|
111 | ## END
|
112 | ## N-I dash/ash status: 2
|
113 | ## N-I dash/ash stdout-json: ""
|
114 | ## N-I mksh status: 1
|
115 | ## N-I mksh stdout-json: ""
|
116 |
|
117 | #### strip unquoted and quoted [
|
118 | # I guess dash and mksh treat unquoted [ as an invalid glob?
|
119 | var='[foo]'
|
120 | echo ${var#[}
|
121 | echo ${var#"["}
|
122 | echo "${var#[}"
|
123 | echo "${var#"["}"
|
124 | ## STDOUT:
|
125 | foo]
|
126 | foo]
|
127 | foo]
|
128 | foo]
|
129 | ## END
|
130 | ## OK mksh STDOUT:
|
131 | [foo]
|
132 | foo]
|
133 | [foo]
|
134 | foo]
|
135 | ## END
|
136 | ## BUG zsh stdout-json: ""
|
137 | ## BUG zsh status: 1
|
138 |
|
139 | #### strip unquoted and quoted []
|
140 | # LooksLikeGlob('[]') is true
|
141 | # I guess dash, mksh, and zsh treat unquoted [ as an invalid glob?
|
142 | var='[]foo[]'
|
143 | echo ${var#[]}
|
144 | echo ${var#"[]"}
|
145 | echo "${var#[]}"
|
146 | echo "${var#"[]"}"
|
147 | ## STDOUT:
|
148 | foo[]
|
149 | foo[]
|
150 | foo[]
|
151 | foo[]
|
152 | ## END
|
153 | ## OK mksh/zsh STDOUT:
|
154 | []foo[]
|
155 | foo[]
|
156 | []foo[]
|
157 | foo[]
|
158 | ## END
|
159 |
|
160 | #### strip unquoted and quoted ?
|
161 | var='[foo]'
|
162 | echo ${var#?}
|
163 | echo ${var#"?"}
|
164 | echo "${var#?}"
|
165 | echo "${var#"?"}"
|
166 | ## STDOUT:
|
167 | foo]
|
168 | [foo]
|
169 | foo]
|
170 | [foo]
|
171 | ## END
|
172 |
|
173 | #### strip unquoted and quoted [a]
|
174 | var='[a]foo[]'
|
175 | echo ${var#[a]}
|
176 | echo ${var#"[a]"}
|
177 | echo "${var#[a]}"
|
178 | echo "${var#"[a]"}"
|
179 | ## STDOUT:
|
180 | [a]foo[]
|
181 | foo[]
|
182 | [a]foo[]
|
183 | foo[]
|
184 | ## END
|
185 |
|
186 | #### Nested % and # operators (bug reported by Crestwave)
|
187 | var=$'\n'
|
188 | argv.py "${var#?}"
|
189 | argv.py "${var%''}"
|
190 | argv.py "${var%"${var#?}"}"
|
191 | var='a'
|
192 | argv.py "${var#?}"
|
193 | argv.py "${var%''}"
|
194 | argv.py "${var%"${var#?}"}"
|
195 | ## STDOUT:
|
196 | ['']
|
197 | ['\n']
|
198 | ['\n']
|
199 | ['']
|
200 | ['a']
|
201 | ['a']
|
202 | ## END
|
203 | ## N-I dash STDOUT:
|
204 | ['\\n']
|
205 | ['$\\n']
|
206 | ['$']
|
207 | ['']
|
208 | ['a']
|
209 | ['a']
|
210 | ## END
|
211 |
|
212 | #### strip * (bug regression)
|
213 | x=abc
|
214 | argv.py "${x#*}"
|
215 | argv.py "${x##*}"
|
216 | argv.py "${x%*}"
|
217 | argv.py "${x%%*}"
|
218 | ## STDOUT:
|
219 | ['abc']
|
220 | ['']
|
221 | ['abc']
|
222 | ['']
|
223 | ## END
|
224 | ## BUG zsh STDOUT:
|
225 | ['abc']
|
226 | ['']
|
227 | ['ab']
|
228 | ['']
|
229 | ## END
|
230 |
|
231 | #### strip ?
|
232 | x=abc
|
233 | argv.py "${x#?}"
|
234 | argv.py "${x##?}"
|
235 | argv.py "${x%?}"
|
236 | argv.py "${x%%?}"
|
237 | ## STDOUT:
|
238 | ['bc']
|
239 | ['bc']
|
240 | ['ab']
|
241 | ['ab']
|
242 | ## END
|
243 |
|
244 | #### strip all
|
245 | x=abc
|
246 | argv.py "${x#abc}"
|
247 | argv.py "${x##abc}"
|
248 | argv.py "${x%abc}"
|
249 | argv.py "${x%%abc}"
|
250 | ## STDOUT:
|
251 | ['']
|
252 | ['']
|
253 | ['']
|
254 | ['']
|
255 | ## END
|
256 |
|
257 | #### strip none
|
258 | x=abc
|
259 | argv.py "${x#}"
|
260 | argv.py "${x##}"
|
261 | argv.py "${x%}"
|
262 | argv.py "${x%%}"
|
263 | ## STDOUT:
|
264 | ['abc']
|
265 | ['abc']
|
266 | ['abc']
|
267 | ['abc']
|
268 | ## END
|
269 |
|
270 | #### strip all unicode
|
271 | x=μabcμ
|
272 | echo "${x#?abc?}"
|
273 | echo "${x##?abc?}"
|
274 | echo "${x%?abc?}"
|
275 | echo "${x%%?abc?}"
|
276 | ## STDOUT:
|
277 |
|
278 |
|
279 |
|
280 |
|
281 | ## BUG dash/mksh/ash STDOUT:
|
282 | μabcμ
|
283 | μabcμ
|
284 | μabcμ
|
285 | μabcμ
|
286 | ## END
|
287 |
|
288 | #### strip none unicode
|
289 | x=μabcμ
|
290 | argv.py "${x#}"
|
291 | argv.py "${x##}"
|
292 | argv.py "${x%}"
|
293 | argv.py "${x%%}"
|
294 | ## STDOUT:
|
295 | ['\xce\xbcabc\xce\xbc']
|
296 | ['\xce\xbcabc\xce\xbc']
|
297 | ['\xce\xbcabc\xce\xbc']
|
298 | ['\xce\xbcabc\xce\xbc']
|
299 | ## END
|
300 |
|
301 | #### Strip Right Brace (#702)
|
302 | var='$foo'
|
303 | echo 1 "${var#$foo}"
|
304 | echo 2 "${var#\$foo}"
|
305 |
|
306 | var='}'
|
307 | echo 10 "${var#}}"
|
308 | echo 11 "${var#\}}"
|
309 | echo 12 "${var#'}'}"
|
310 | echo 13 "${var#"}"}"
|
311 | ## STDOUT:
|
312 | 1 $foo
|
313 | 2
|
314 | 10 }}
|
315 | 11
|
316 | 12
|
317 | 13
|
318 | ## END
|
319 | ## BUG zsh STDOUT:
|
320 | 1 $foo
|
321 | 2
|
322 | 10 }}
|
323 | 11
|
324 | 12 }'}
|
325 | 13
|
326 | ## END
|
327 |
|
328 | #### \(\) in pattern (regression)
|
329 | x='foo()'
|
330 | echo 1 ${x%*\(\)}
|
331 | echo 2 ${x%%*\(\)}
|
332 | echo 3 ${x#*\(\)}
|
333 | echo 4 ${x##*\(\)}
|
334 | ## STDOUT:
|
335 | 1 foo
|
336 | 2
|
337 | 3
|
338 | 4
|
339 | ## END
|
340 |
|
341 | #### extglob in pattern
|
342 | case $SH in (dash|zsh|ash) exit ;; esac
|
343 |
|
344 | shopt -s extglob
|
345 |
|
346 | x='foo()'
|
347 | echo 1 ${x%*(foo|bar)'()'}
|
348 | echo 2 ${x%%*(foo|bar)'()'}
|
349 | echo 3 ${x#*(foo|bar)'()'}
|
350 | echo 4 ${x##*(foo|bar)'()'}
|
351 | ## STDOUT:
|
352 | 1 foo
|
353 | 2
|
354 | 3
|
355 | 4
|
356 | ## END
|
357 | ## N-I dash/zsh/ash stdout-json: ""
|