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: ["'a b c "]
165
166 #### The string to strip is space sensitive
167 foo='a b c d'
168 argv.py "${foo%c d}" "${foo%c d}"
169 ## stdout: ['a b ', 'a b c d']
170
171 #### The string to strip can be single quoted, outer is unquoted
172 foo='a b c d'
173 argv.py ${foo%'c d'} ${foo%'c d'}
174 ## stdout: ['a', 'b', 'a', 'b', 'c', 'd']
175
176 #### Strip a string with single quotes, double quoted, with unescaped '
177 # We're in a double quoted context, so we should be able to use a literal
178 # single quote. This is very much the case with :-.
179 foo="'a b c d'"
180 argv.py "${foo%d'}"
181 ## stdout: ["'a b c "]
182 ## BUG bash/mksh stdout-json: ""
183 ## BUG bash status: 2
184 ## BUG mksh status: 1
185
186 #### The string to strip can be single quoted, outer is double quoted
187 # This is an inconsistency in bash/mksh because '' are treated as literals in
188 # double quotes. The correct ways are above.
189 foo='a b c d'
190 argv.py "${foo%'c d'}" "${foo%'c d'}"
191 ## stdout: ['a b c d', 'a b c d']
192 ## BUG bash/mksh stdout: ['a b ', 'a b c d']
193
194 #### $'' allowed within VarSub arguments
195 # Odd behavior of bash/mksh: $'' is recognized but NOT ''!
196 x=abc
197 echo ${x%$'b'*}
198 echo "${x%$'b'*}" # git-prompt.sh relies on this
199 ## STDOUT:
200 a
201 a
202 ## END
203 ## N-I dash STDOUT:
204 abc
205 abc
206 ## END
207
208 #### # operator with single quoted arg (dash/ash and bash/mksh disagree, reported by Crestwave)
209 var=a
210 echo -${var#'a'}-
211 echo -"${var#'a'}"-
212 var="'a'"
213 echo -${var#'a'}-
214 echo -"${var#'a'}"-
215 ## STDOUT:
216 --
217 --
218 -'a'-
219 -'a'-
220 ## END
221 ## OK dash/ash STDOUT:
222 --
223 -a-
224 -'a'-
225 --
226 ## END
227
228 #### / operator with single quoted arg (causes syntax error in regex in OSH, reported by Crestwave)
229 var="++--''++--''"
230 echo no plus or minus "${var//[+-]}"
231 echo no plus or minus "${var//['+-']}"
232 ## STDOUT:
233 no plus or minus ''''
234 no plus or minus ''''
235 ## END
236 ## status: 0
237 ## OK osh STDOUT:
238 no plus or minus ''''
239 ## END
240 ## OK osh status: 1
241 ## BUG ash STDOUT:
242 no plus or minus ''''
243 no plus or minus ++--++--
244 ## END
245 ## BUG ash status: 0
246 ## N-I dash stdout-json: ""
247 ## N-I dash status: 2
248
249 #### single quotes work inside character classes
250 x='a[[[---]]]b'
251 echo "${x//['[]']}"
252 ## STDOUT:
253 a---b
254 ## END
255 ## BUG ash STDOUT:
256 a[[[---]]]b
257 ## END
258 ## N-I dash stdout-json: ""
259 ## N-I dash status: 2
260
261 #### comparison: :- operator with single quoted arg
262 echo ${unset:-'a'}
263 echo "${unset:-'a'}"
264 ## STDOUT:
265 a
266 'a'
267 ## END