1 #!/usr/bin/env bash
2 #
3 # Tests for the args in:
4 #
5 # ${foo:-}
6 #
7 # I think the weird single quote behavior is a bug, but everyone agrees. It's
8 # a consequence of quote removal.
9 #
10 # WEIRD: single quoted default, inside double quotes. Oh I guess this is
11 # because double quotes don't treat single quotes as special?
12 #
13 # OK here is the issue. If we have ${} bare, then the default is parsed as
14 # LexState.OUTER. If we have "${}", then it's parsed as LexState.DQ. That
15 # makes sense I guess. Vim's syntax highlighting is throwing me off.
16
17 #### "${empty:-}"
18 empty=
19 argv.py "${empty:-}"
20 ## stdout: ['']
21
22 #### ${empty:-}
23 empty=
24 argv.py ${empty:-}
25 ## stdout: []
26
27 #### array with empty values
28 declare -a A=('' x "" '')
29 argv.py "${A[@]}"
30 ## stdout: ['', 'x', '', '']
31 ## N-I dash stdout-json: ""
32 ## N-I dash status: 2
33 ## N-I mksh stdout-json: ""
34 ## N-I mksh status: 1
35
36 #### substitution of IFS character, quoted and unquoted
37 IFS=:
38 s=:
39 argv.py $s
40 argv.py "$s"
41 ## STDOUT:
42 ['']
43 [':']
44 ## END
45
46 #### :-
47 empty=''
48 argv.py ${empty:-a} ${Unset:-b}
49 ## stdout: ['a', 'b']
50
51 #### -
52 empty=''
53 argv.py ${empty-a} ${Unset-b}
54 # empty one is still elided!
55 ## stdout: ['b']
56
57 #### Inner single quotes
58 argv.py ${Unset:-'b'}
59 ## stdout: ['b']
60
61 #### Inner single quotes, outer double quotes
62 # This is the WEIRD ONE. Single quotes appear outside. But all shells agree!
63 argv.py "${Unset:-'b'}"
64 ## stdout: ["'b'"]
65
66 #### Inner double quotes
67 argv.py ${Unset:-"b"}
68 ## stdout: ['b']
69
70 #### Inner double quotes, outer double quotes
71 argv.py "${Unset-"b"}"
72 ## stdout: ['b']
73
74 #### Multiple words: no quotes
75 argv.py ${Unset:-a b c}
76 ## stdout: ['a', 'b', 'c']
77
78 #### Multiple words: no outer quotes, inner single quotes
79 argv.py ${Unset:-'a b c'}
80 ## stdout: ['a b c']
81
82 #### Multiple words: no outer quotes, inner double quotes
83 argv.py ${Unset:-"a b c"}
84 ## stdout: ['a b c']
85
86 #### Multiple words: outer double quotes, no inner quotes
87 argv.py "${Unset:-a b c}"
88 ## stdout: ['a b c']
89
90 #### Multiple words: outer double quotes, inner double quotes
91 argv.py "${Unset:-"a b c"}"
92 ## stdout: ['a b c']
93
94 #### Multiple words: outer double quotes, inner single quotes
95 argv.py "${Unset:-'a b c'}"
96 # WEIRD ONE.
97 ## stdout: ["'a b c'"]
98
99 #### Mixed inner quotes
100 argv.py ${Unset:-"a b" c}
101 ## stdout: ['a b', 'c']
102
103 #### Mixed inner quotes with outer quotes
104 argv.py "${Unset:-"a b" c}"
105 ## stdout: ['a b c']
106
107 #### part_value tree with multiple words
108 argv.py ${a:-${a:-"1 2" "3 4"}5 "6 7"}
109 ## stdout: ['1 2', '3 45', '6 7']
110
111 #### part_value tree on RHS
112 v=${a:-${a:-"1 2" "3 4"}5 "6 7"}
113 argv.py "${v}"
114 ## stdout: ['1 2 3 45 6 7']
115
116 #### Var with multiple words: no quotes
117 var='a b c'
118 argv.py ${Unset:-$var}
119 ## stdout: ['a', 'b', 'c']
120
121 #### Multiple words: no outer quotes, inner single quotes
122 var='a b c'
123 argv.py ${Unset:-'$var'}
124 ## stdout: ['$var']
125
126 #### Multiple words: no outer quotes, inner double quotes
127 var='a b c'
128 argv.py ${Unset:-"$var"}
129 ## stdout: ['a b c']
130
131 #### Multiple words: outer double quotes, no inner quotes
132 var='a b c'
133 argv.py "${Unset:-$var}"
134 ## stdout: ['a b c']
135
136 #### Multiple words: outer double quotes, inner double quotes
137 var='a b c'
138 argv.py "${Unset:-"$var"}"
139 ## stdout: ['a b c']
140
141 #### Multiple words: outer double quotes, inner single quotes
142 # WEIRD ONE.
143 #
144 # I think I should just disallow any word with single quotes inside double
145 # quotes.
146 var='a b c'
147 argv.py "${Unset:-'$var'}"
148 ## stdout: ["'a b c'"]
149
150 #### No outer quotes, Multiple internal quotes
151 # It's like a single command word. Parts are joined directly.
152 var='a b c'
153 argv.py ${Unset:-A$var " $var"D E F}
154 ## stdout: ['Aa', 'b', 'c', ' a b cD', 'E', 'F']
155
156 #### Strip a string with single quotes, unquoted
157 foo="'a b c d'"
158 argv.py ${foo%d\'}
159 ## stdout: ["'a", 'b', 'c']
160
161 #### Strip a string with single quotes, double quoted
162 foo="'a b c d'"
163 argv.py "${foo%d\'}"
164 ## STDOUT:
165 ["'a b c "]
166 ## END
167
168 #### The string to strip is space sensitive
169 foo='a b c d'
170 argv.py "${foo%c d}" "${foo%c d}"
171 ## stdout: ['a b ', 'a b c d']
172
173 #### The string to strip can be single quoted, outer is unquoted
174 foo='a b c d'
175 argv.py ${foo%'c d'} ${foo%'c d'}
176 ## stdout: ['a', 'b', 'a', 'b', 'c', 'd']
177
178 #### Syntax error for single quote in double quote
179 foo="'a b c d'"
180 argv.py "${foo%d'}"
181 ## stdout-json: ""
182 ## status: 2
183 ## OK mksh status: 1
184
185 #### "${undef-'c d'}" and "${foo%'c d'}" are parsed differently
186
187 # quotes are LITERAL here
188 argv.py "${undef-'c d'}" "${undef-'c d'}"
189 argv.py ${undef-'c d'} ${undef-'c d'}
190
191 echo ---
192
193 # quotes are RESPECTED here
194 foo='a b c d'
195 argv.py "${foo%'c d'}" "${foo%'c d'}"
196
197 case $SH in (dash) exit ;; esac
198
199 argv.py "${foo//'c d'/zzz}" "${foo//'c d'/zzz}"
200 argv.py "${foo//'c d'/'zzz'}" "${foo//'c d'/'zzz'}"
201
202 ## STDOUT:
203 ["'c d'", "'c d'"]
204 ['c d', 'c d']
205 ---
206 ['a b ', 'a b c d']
207 ['a b zzz', 'a b c d']
208 ['a b zzz', 'a b c d']
209 ## END
210 ## OK dash STDOUT:
211 ["'c d'", "'c d'"]
212 ['c d', 'c d']
213 ---
214 ['a b ', 'a b c d']
215 ## END
216
217 #### $'' allowed within VarSub arguments
218 # Odd behavior of bash/mksh: $'' is recognized but NOT ''!
219 x=abc
220 echo ${x%$'b'*}
221 echo "${x%$'b'*}" # git-prompt.sh relies on this
222 ## STDOUT:
223 a
224 a
225 ## END
226 ## N-I dash STDOUT:
227 abc
228 abc
229 ## END
230
231 #### # operator with single quoted arg (dash/ash and bash/mksh disagree, reported by Crestwave)
232 var=a
233 echo -${var#'a'}-
234 echo -"${var#'a'}"-
235 var="'a'"
236 echo -${var#'a'}-
237 echo -"${var#'a'}"-
238 ## STDOUT:
239 --
240 --
241 -'a'-
242 -'a'-
243 ## END
244 ## OK ash STDOUT:
245 --
246 -a-
247 -'a'-
248 --
249 ## END
250
251 #### / operator with single quoted arg (causes syntax error in regex in OSH, reported by Crestwave)
252 var="++--''++--''"
253 echo no plus or minus "${var//[+-]}"
254 echo no plus or minus "${var//['+-']}"
255 ## STDOUT:
256 no plus or minus ''''
257 no plus or minus ''''
258 ## END
259 ## status: 0
260 ## BUG ash STDOUT:
261 no plus or minus ''''
262 no plus or minus ++--++--
263 ## END
264 ## BUG ash status: 0
265 ## N-I dash stdout-json: ""
266 ## N-I dash status: 2
267
268 #### single quotes work inside character classes
269 x='a[[[---]]]b'
270 echo "${x//['[]']}"
271 ## STDOUT:
272 a---b
273 ## END
274 ## BUG ash STDOUT:
275 a[[[---]]]b
276 ## END
277 ## N-I dash stdout-json: ""
278 ## N-I dash status: 2
279
280 #### comparison: :- operator with single quoted arg
281 echo ${unset:-'a'}
282 echo "${unset:-'a'}"
283 ## STDOUT:
284 a
285 'a'
286 ## END
287
288
289 #### Right Brace as argument (similar to #702)
290
291 echo "${var-}}"
292 echo "${var-\}}"
293 echo "${var-'}'}"
294 echo "${var-"}"}"
295 ## STDOUT:
296 }
297 }
298 ''}
299 }
300 ## END
301 ## BUG bash STDOUT:
302 }
303 }
304 '}'
305 }
306 ## END
307 ## BUG yash STDOUT:
308 }
309 }
310 }
311 }
312 ## END
313