1 |
#!/usr/bin/env bash |
2 |
# |
3 |
# Test combination of var ops. |
4 |
# |
5 |
# NOTE: There are also slice tests in {array,arith-context}.test.sh. |
6 |
|
7 |
#### String length |
8 |
v=foo |
9 |
echo ${#v} |
10 |
## stdout: 3 |
11 |
|
12 |
#### Unicode string length (UTF-8) |
13 |
v=$'_\u03bc_' |
14 |
echo ${#v} |
15 |
## stdout: 3 |
16 |
## N-I dash stdout: 9 |
17 |
## N-I mksh stdout: 4 |
18 |
|
19 |
#### Unicode string length (spec/testdata/utf8-chars.txt) |
20 |
v=$(cat spec/testdata/utf8-chars.txt) |
21 |
echo ${#v} |
22 |
## stdout: 7 |
23 |
## N-I dash stdout: 13 |
24 |
## N-I mksh stdout: 13 |
25 |
|
26 |
#### String length with incomplete utf-8 |
27 |
for num_bytes in 0 1 2 3 4 5 6 7 8 9 10 11 12 13; do |
28 |
s=$(head -c $num_bytes spec/testdata/utf8-chars.txt) |
29 |
echo ${#s} |
30 |
done |
31 |
## STDOUT: |
32 |
0 |
33 |
1 |
34 |
2 |
35 |
error: Incomplete utf-8 |
36 |
3 |
37 |
4 |
38 |
error: Incomplete utf-8 |
39 |
error: Incomplete utf-8 |
40 |
5 |
41 |
6 |
42 |
error: Incomplete utf-8 |
43 |
error: Incomplete utf-8 |
44 |
error: Incomplete utf-8 |
45 |
7 |
46 |
## END |
47 |
## BUG bash STDOUT: |
48 |
0 |
49 |
1 |
50 |
2 |
51 |
3 |
52 |
3 |
53 |
4 |
54 |
5 |
55 |
6 |
56 |
5 |
57 |
6 |
58 |
7 |
59 |
8 |
60 |
9 |
61 |
7 |
62 |
## END |
63 |
## N-I dash/mksh STDOUT: |
64 |
0 |
65 |
1 |
66 |
2 |
67 |
3 |
68 |
4 |
69 |
5 |
70 |
6 |
71 |
7 |
72 |
8 |
73 |
9 |
74 |
10 |
75 |
11 |
76 |
12 |
77 |
13 |
78 |
## END |
79 |
|
80 |
#### String length with invalid utf-8 continuation bytes |
81 |
for num_bytes in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14; do |
82 |
s=$(head -c $num_bytes spec/testdata/utf8-chars.txt)$(echo -e "\xFF") |
83 |
echo ${#s} |
84 |
done |
85 |
## STDOUT: |
86 |
error: Invalid start of utf-8 char |
87 |
error: Invalid start of utf-8 char |
88 |
error: Invalid start of utf-8 char |
89 |
error: Invalid utf-8 continuation byte |
90 |
error: Invalid start of utf-8 char |
91 |
error: Invalid start of utf-8 char |
92 |
error: Invalid utf-8 continuation byte |
93 |
error: Invalid utf-8 continuation byte |
94 |
error: Invalid start of utf-8 char |
95 |
error: Invalid start of utf-8 char |
96 |
error: Invalid utf-8 continuation byte |
97 |
error: Invalid utf-8 continuation byte |
98 |
error: Invalid utf-8 continuation byte |
99 |
error: Invalid start of utf-8 char |
100 |
error: Invalid start of utf-8 char |
101 |
## END |
102 |
## BUG bash STDOUT: |
103 |
1 |
104 |
2 |
105 |
3 |
106 |
4 |
107 |
4 |
108 |
5 |
109 |
6 |
110 |
7 |
111 |
6 |
112 |
7 |
113 |
8 |
114 |
9 |
115 |
10 |
116 |
8 |
117 |
8 |
118 |
## N-I dash STDOUT: |
119 |
7 |
120 |
8 |
121 |
9 |
122 |
10 |
123 |
11 |
124 |
12 |
125 |
13 |
126 |
14 |
127 |
15 |
128 |
16 |
129 |
17 |
130 |
18 |
131 |
19 |
132 |
20 |
133 |
20 |
134 |
## END |
135 |
## N-I mksh STDOUT: |
136 |
1 |
137 |
2 |
138 |
3 |
139 |
4 |
140 |
5 |
141 |
6 |
142 |
7 |
143 |
8 |
144 |
9 |
145 |
10 |
146 |
11 |
147 |
12 |
148 |
13 |
149 |
14 |
150 |
14 |
151 |
## END |
152 |
|
153 |
#### Length of undefined variable |
154 |
echo ${#undef} |
155 |
## stdout: 0 |
156 |
|
157 |
#### Length of undefined variable with nounset |
158 |
set -o nounset |
159 |
echo ${#undef} |
160 |
## status: 1 |
161 |
## OK dash status: 2 |
162 |
|
163 |
#### Cannot take length of substring slice |
164 |
# These are runtime errors, but we could make them parse time errors. |
165 |
v=abcde |
166 |
echo ${#v:1:3} |
167 |
## status: 1 |
168 |
## OK osh status: 2 |
169 |
## N-I dash status: 0 |
170 |
## N-I dash stdout: 5 |
171 |
|
172 |
#### Pattern replacement |
173 |
v=abcde |
174 |
echo ${v/c*/XX} |
175 |
## stdout: abXX |
176 |
## N-I dash status: 2 |
177 |
## N-I dash stdout-json: "" |
178 |
|
179 |
#### Pattern replacement on unset variable |
180 |
echo [${v/x/y}] |
181 |
echo status=$? |
182 |
set -o nounset # make sure this fails |
183 |
echo [${v/x/y}] |
184 |
## STDOUT: |
185 |
[] |
186 |
status=0 |
187 |
## BUG mksh STDOUT: |
188 |
# patsub disrespects nounset! |
189 |
[] |
190 |
status=0 |
191 |
[] |
192 |
## status: 1 |
193 |
## BUG mksh status: 0 |
194 |
## N-I dash status: 2 |
195 |
## N-I dash stdout-json: "" |
196 |
|
197 |
#### Global Pattern replacement with / |
198 |
s=xx_xx_xx |
199 |
echo ${s/xx?/yy_} ${s//xx?/yy_} |
200 |
## stdout: yy_xx_xx yy_yy_xx |
201 |
## N-I dash status: 2 |
202 |
## N-I dash stdout-json: "" |
203 |
|
204 |
#### Left Anchored Pattern replacement with # |
205 |
s=xx_xx_xx |
206 |
echo ${s/?xx/_yy} ${s/#?xx/_yy} |
207 |
## stdout: xx_yy_xx xx_xx_xx |
208 |
## N-I dash status: 2 |
209 |
## N-I dash stdout-json: "" |
210 |
|
211 |
#### Right Anchored Pattern replacement with % |
212 |
s=xx_xx_xx |
213 |
echo ${s/?xx/_yy} ${s/%?xx/_yy} |
214 |
## stdout: xx_yy_xx xx_xx_yy |
215 |
## N-I dash status: 2 |
216 |
## N-I dash stdout-json: "" |
217 |
|
218 |
#### Replace fixed strings |
219 |
s=xx_xx |
220 |
echo ${s/xx/yy} ${s//xx/yy} ${s/#xx/yy} ${s/%xx/yy} |
221 |
## stdout: yy_xx yy_yy yy_xx xx_yy |
222 |
## N-I dash status: 2 |
223 |
## N-I dash stdout-json: "" |
224 |
|
225 |
#### Replace is longest match |
226 |
# If it were shortest, then you would just replace the first <html> |
227 |
s='begin <html></html> end' |
228 |
echo ${s/<*>/[]} |
229 |
## stdout: begin [] end |
230 |
## N-I dash status: 2 |
231 |
## N-I dash stdout-json: "" |
232 |
|
233 |
#### Replace char class |
234 |
s=xx_xx_xx |
235 |
echo ${s//[[:alpha:]]/y} ${s//[^[:alpha:]]/-} |
236 |
## stdout: yy_yy_yy xx-xx-xx |
237 |
## N-I mksh stdout: xx_xx_xx xx_xx_xx |
238 |
## N-I dash status: 2 |
239 |
## N-I dash stdout-json: "" |
240 |
|
241 |
#### Replace hard glob |
242 |
s='aa*bb+cc' |
243 |
echo ${s//\**+/__} # Literal *, then any sequence of characters, then literal + |
244 |
## stdout: aa__cc |
245 |
## N-I dash status: 2 |
246 |
## N-I dash stdout-json: "" |
247 |
|
248 |
#### Pattern replacement ${v/} is not valid |
249 |
v=abcde |
250 |
echo -${v/}- |
251 |
echo status=$? |
252 |
## status: 2 |
253 |
## stdout-json: "" |
254 |
## N-I dash status: 2 |
255 |
## N-I dash stdout-json: "" |
256 |
## BUG bash/mksh status: 0 |
257 |
## BUG bash/mksh stdout-json: "-abcde-\nstatus=0\n" |
258 |
|
259 |
#### Pattern replacement ${v//} is not valid |
260 |
v='a/b/c' |
261 |
echo -${v//}- |
262 |
echo status=$? |
263 |
## status: 2 |
264 |
## stdout-json: "" |
265 |
## N-I dash status: 2 |
266 |
## N-I dash stdout-json: "" |
267 |
## BUG bash/mksh status: 0 |
268 |
## BUG bash/mksh stdout-json: "-a/b/c-\nstatus=0\n" |
269 |
|
270 |
#### ${v/a} is the same as ${v/a/} -- no replacement string |
271 |
v='aabb' |
272 |
echo ${v/a} |
273 |
echo status=$? |
274 |
## stdout-json: "abb\nstatus=0\n" |
275 |
## N-I dash stdout-json: "" |
276 |
## N-I dash status: 2 |
277 |
|
278 |
#### String slice |
279 |
foo=abcdefg |
280 |
echo ${foo:1:3} |
281 |
## stdout: bcd |
282 |
## N-I dash status: 2 |
283 |
## N-I dash stdout-json: "" |
284 |
|
285 |
#### Negative string slice |
286 |
foo=abcdefg |
287 |
echo ${foo: -4:3} |
288 |
## stdout: def |
289 |
## N-I dash status: 2 |
290 |
## N-I dash stdout-json: "" |
291 |
|
292 |
#### String slice with math |
293 |
# I think this is the $(()) language inside? |
294 |
i=1 |
295 |
foo=abcdefg |
296 |
echo ${foo: i-3-2 : i + 2} |
297 |
## stdout: def |
298 |
## N-I dash status: 2 |
299 |
## N-I dash stdout-json: "" |
300 |
|
301 |
#### Slice String with Unicode |
302 |
# mksh slices by bytes. |
303 |
foo='--μ--' |
304 |
echo ${foo:1:3} |
305 |
## stdout: -μ- |
306 |
## BUG mksh stdout: -μ |
307 |
## N-I dash status: 2 |
308 |
## N-I dash stdout-json: "" |