1 |
# printf |
2 |
# bash-completion uses this odd printf -v construction. It seems to mostly use |
3 |
# %s and %q though. |
4 |
# |
5 |
# %s should just be |
6 |
# declare $var='val' |
7 |
# |
8 |
# NOTE: |
9 |
# /usr/bin/printf %q "'" seems wrong. |
10 |
# $ /usr/bin/printf %q "'" |
11 |
# ''\''' |
12 |
# |
13 |
# I suppose it is technically correct, but it looks very ugly. |
14 |
|
15 |
#### printf with no args |
16 |
printf |
17 |
## status: 2 |
18 |
## OK mksh/zsh status: 1 |
19 |
## stdout-json: "" |
20 |
|
21 |
#### printf -v %s |
22 |
var=foo |
23 |
printf -v $var %s 'hello there' |
24 |
argv.py "$foo" |
25 |
## STDOUT: |
26 |
['hello there'] |
27 |
## END |
28 |
## N-I mksh/zsh/ash STDOUT: |
29 |
-v[''] |
30 |
## END |
31 |
## N-I dash STDOUT: |
32 |
[''] |
33 |
## END |
34 |
|
35 |
#### printf -v %q |
36 |
val='"quoted" with spaces and \' |
37 |
|
38 |
# quote 'val' and store it in foo |
39 |
printf -v foo %q "$val" |
40 |
# then round trip back to eval |
41 |
eval "bar=$foo" |
42 |
|
43 |
# debugging: |
44 |
#echo foo="$foo" |
45 |
#echo bar="$bar" |
46 |
#echo val="$val" |
47 |
|
48 |
test "$bar" = "$val" && echo OK |
49 |
## STDOUT: |
50 |
OK |
51 |
## END |
52 |
## N-I mksh/zsh/ash stdout-json: "-v" |
53 |
## N-I mksh/zsh/ash status: 1 |
54 |
## N-I dash stdout-json: "" |
55 |
## N-I dash status: 1 |
56 |
|
57 |
#### printf -v a[1] |
58 |
shopt -s eval_unsafe_arith |
59 |
a=(a b c) |
60 |
printf -v 'a[1]' %s 'foo' |
61 |
echo status=$? |
62 |
argv.py "${a[@]}" |
63 |
## STDOUT: |
64 |
status=0 |
65 |
['a', 'foo', 'c'] |
66 |
## END |
67 |
## N-I mksh/zsh STDOUT: |
68 |
-vstatus=0 |
69 |
['a', 'b', 'c'] |
70 |
## END |
71 |
## N-I dash/ash stdout-json: "" |
72 |
## N-I dash/ash status: 2 |
73 |
|
74 |
#### printf -v syntax error |
75 |
shopt -s eval_unsafe_arith |
76 |
printf -v 'a[' %s 'foo' |
77 |
echo status=$? |
78 |
## STDOUT: |
79 |
status=2 |
80 |
## END |
81 |
## N-I ash/mksh/zsh stdout: -vstatus=0 |
82 |
|
83 |
#### dynamic declare instead of %s |
84 |
var=foo |
85 |
declare $var='hello there' |
86 |
argv.py "$foo" |
87 |
## STDOUT: |
88 |
['hello there'] |
89 |
## END |
90 |
## N-I dash/mksh/ash STDOUT: |
91 |
[''] |
92 |
## END |
93 |
|
94 |
#### dynamic declare instead of %q |
95 |
var=foo |
96 |
val='"quoted" with spaces and \' |
97 |
# I think this is bash 4.4 only. |
98 |
declare $var="${val@Q}" |
99 |
echo "$foo" |
100 |
## STDOUT: |
101 |
'"quoted" with spaces and \' |
102 |
## END |
103 |
## OK osh STDOUT: |
104 |
$'"quoted" with spaces and \\' |
105 |
## END |
106 |
## N-I dash/ash stdout-json: "" |
107 |
## N-I dash/ash status: 2 |
108 |
## N-I mksh stdout-json: "\n" |
109 |
## N-I zsh stdout-json: "" |
110 |
## N-I zsh status: 1 |
111 |
|
112 |
#### printf -v dynamic scope |
113 |
case $SH in mksh|zsh|dash|ash) echo not implemented; exit ;; esac |
114 |
# OK so printf is like assigning to a var. |
115 |
# printf -v foo %q "$bar" is like |
116 |
# foo=${bar@Q} |
117 |
dollar='dollar' |
118 |
f() { |
119 |
local mylocal=foo |
120 |
printf -v dollar %q '$' # assign foo to a quoted dollar |
121 |
printf -v mylocal %q 'mylocal' |
122 |
echo dollar=$dollar |
123 |
echo mylocal=$mylocal |
124 |
} |
125 |
echo dollar=$dollar |
126 |
echo -- |
127 |
f |
128 |
echo -- |
129 |
echo dollar=$dollar |
130 |
echo mylocal=$mylocal |
131 |
## STDOUT: |
132 |
dollar=dollar |
133 |
-- |
134 |
dollar=\$ |
135 |
mylocal=mylocal |
136 |
-- |
137 |
dollar=\$ |
138 |
mylocal= |
139 |
## END |
140 |
## OK osh STDOUT: |
141 |
dollar=dollar |
142 |
-- |
143 |
dollar='$' |
144 |
mylocal=mylocal |
145 |
-- |
146 |
dollar='$' |
147 |
mylocal= |
148 |
## END |
149 |
## N-I dash/ash/mksh/zsh STDOUT: |
150 |
not implemented |
151 |
## END |
152 |
|
153 |
#### printf with too few arguments |
154 |
printf -- '-%s-%s-%s-\n' 'a b' 'x y' |
155 |
## STDOUT: |
156 |
-a b-x y-- |
157 |
## END |
158 |
|
159 |
#### printf with too many arguments |
160 |
printf -- '-%s-%s-\n' a b c d e |
161 |
## STDOUT: |
162 |
-a-b- |
163 |
-c-d- |
164 |
-e-- |
165 |
## END |
166 |
|
167 |
#### printf width strings |
168 |
printf '[%5s]\n' abc |
169 |
printf '[%-5s]\n' abc |
170 |
## STDOUT: |
171 |
[ abc] |
172 |
[abc ] |
173 |
## END |
174 |
|
175 |
#### printf integer |
176 |
printf '%d\n' 42 |
177 |
printf '%i\n' 42 # synonym |
178 |
printf '%d\n' \'a # if first character is a quote, use character code |
179 |
printf '%d\n' \"a # double quotes work too |
180 |
printf '[%5d]\n' 42 |
181 |
printf '[%-5d]\n' 42 |
182 |
printf '[%05d]\n' 42 |
183 |
#printf '[%-05d]\n' 42 # the leading 0 is meaningless |
184 |
#[42 ] |
185 |
## STDOUT: |
186 |
42 |
187 |
42 |
188 |
97 |
189 |
97 |
190 |
[ 42] |
191 |
[42 ] |
192 |
[00042] |
193 |
## END |
194 |
|
195 |
#### printf %6.4d -- "precision" does padding for integers |
196 |
printf '[%6.4d]\n' 42 |
197 |
printf '[%.4d]\n' 42 |
198 |
printf '[%6.d]\n' 42 |
199 |
echo -- |
200 |
printf '[%6.4d]\n' -42 |
201 |
printf '[%.4d]\n' -42 |
202 |
printf '[%6.d]\n' -42 |
203 |
## STDOUT: |
204 |
[ 0042] |
205 |
[0042] |
206 |
[ 42] |
207 |
-- |
208 |
[ -0042] |
209 |
[-0042] |
210 |
[ -42] |
211 |
## END |
212 |
|
213 |
#### printf %6.4x X o |
214 |
printf '[%6.4x]\n' 42 |
215 |
printf '[%.4x]\n' 42 |
216 |
printf '[%6.x]\n' 42 |
217 |
echo -- |
218 |
printf '[%6.4X]\n' 42 |
219 |
printf '[%.4X]\n' 42 |
220 |
printf '[%6.X]\n' 42 |
221 |
echo -- |
222 |
printf '[%6.4o]\n' 42 |
223 |
printf '[%.4o]\n' 42 |
224 |
printf '[%6.o]\n' 42 |
225 |
## STDOUT: |
226 |
[ 002a] |
227 |
[002a] |
228 |
[ 2a] |
229 |
-- |
230 |
[ 002A] |
231 |
[002A] |
232 |
[ 2A] |
233 |
-- |
234 |
[ 0052] |
235 |
[0052] |
236 |
[ 52] |
237 |
## END |
238 |
|
239 |
#### %06d zero padding vs. %6.6d |
240 |
printf '[%06d]\n' 42 |
241 |
printf '[%06d]\n' -42 # 6 TOTAL |
242 |
echo -- |
243 |
printf '[%6.6d]\n' 42 |
244 |
printf '[%6.6d]\n' -42 # 6 + 1 for the - sign!!! |
245 |
## STDOUT: |
246 |
[000042] |
247 |
[-00042] |
248 |
-- |
249 |
[000042] |
250 |
[-000042] |
251 |
## END |
252 |
|
253 |
#### %06x %06X %06o |
254 |
printf '[%06x]\n' 42 |
255 |
printf '[%06X]\n' 42 |
256 |
printf '[%06o]\n' 42 |
257 |
## STDOUT: |
258 |
[00002a] |
259 |
[00002A] |
260 |
[000052] |
261 |
## END |
262 |
|
263 |
#### %06s is no-op |
264 |
printf '(%6s)\n' 42 |
265 |
printf '(%6s)\n' -42 |
266 |
printf '(%06s)\n' 42 |
267 |
printf '(%06s)\n' -42 |
268 |
echo status=$? |
269 |
## STDOUT: |
270 |
( 42) |
271 |
( -42) |
272 |
( 42) |
273 |
( -42) |
274 |
status=0 |
275 |
## END |
276 |
# mksh is stricter |
277 |
## OK mksh STDOUT: |
278 |
( 42) |
279 |
( -42) |
280 |
((status=1 |
281 |
## END |
282 |
|
283 |
#### printf %6.4s does both truncation and padding |
284 |
printf '[%6s]\n' foo |
285 |
printf '[%6.4s]\n' foo |
286 |
printf '[%-6.4s]\n' foo |
287 |
printf '[%6s]\n' spam-eggs |
288 |
printf '[%6.4s]\n' spam-eggs |
289 |
printf '[%-6.4s]\n' spam-eggs |
290 |
## STDOUT: |
291 |
[ foo] |
292 |
[ foo] |
293 |
[foo ] |
294 |
[spam-eggs] |
295 |
[ spam] |
296 |
[spam ] |
297 |
## END |
298 |
|
299 |
#### printf %6.0s and %0.0s |
300 |
printf '[%6.0s]\n' foo |
301 |
printf '[%0.0s]\n' foo |
302 |
## STDOUT: |
303 |
[ ] |
304 |
[] |
305 |
## END |
306 |
## N-I mksh stdout-json: "[ ]\n[" |
307 |
## N-I mksh status: 1 |
308 |
|
309 |
#### printf %6.s and %0.s |
310 |
printf '[%6.s]\n' foo |
311 |
printf '[%0.s]\n' foo |
312 |
## STDOUT: |
313 |
[ ] |
314 |
[] |
315 |
## END |
316 |
## BUG zsh STDOUT: |
317 |
[ foo] |
318 |
[foo] |
319 |
## END |
320 |
## N-I mksh stdout-json: "[ ]\n[" |
321 |
## N-I mksh status: 1 |
322 |
|
323 |
#### printf %*.*s (width/precision from args) |
324 |
printf '[%*s]\n' 9 hello |
325 |
printf '[%.*s]\n' 3 hello |
326 |
printf '[%*.3s]\n' 9 hello |
327 |
printf '[%9.*s]\n' 3 hello |
328 |
printf '[%*.*s]\n' 9 3 hello |
329 |
## STDOUT: |
330 |
[ hello] |
331 |
[hel] |
332 |
[ hel] |
333 |
[ hel] |
334 |
[ hel] |
335 |
## END |
336 |
|
337 |
#### unsigned / octal / hex |
338 |
printf '[%u]\n' 42 |
339 |
printf '[%o]\n' 42 |
340 |
printf '[%x]\n' 42 |
341 |
printf '[%X]\n' 42 |
342 |
printf '[%X]\n' \'a # if first character is a quote, use character code |
343 |
printf '[%X]\n' \'ab # extra chars ignored |
344 |
## STDOUT: |
345 |
[42] |
346 |
[52] |
347 |
[2a] |
348 |
[2A] |
349 |
[61] |
350 |
[61] |
351 |
## END |
352 |
|
353 |
#### empty string (osh is more strict) |
354 |
printf '%d\n' '' |
355 |
## OK osh stdout-json: "" |
356 |
## OK osh status: 1 |
357 |
## OK ash status: 1 |
358 |
## STDOUT: |
359 |
0 |
360 |
## END |
361 |
|
362 |
#### No char after ' (osh is more strict) |
363 |
|
364 |
# most shells use 0 here |
365 |
printf '%d\n' \' |
366 |
printf '%d\n' \" |
367 |
|
368 |
## OK mksh status: 1 |
369 |
## STDOUT: |
370 |
0 |
371 |
0 |
372 |
## END |
373 |
|
374 |
#### Unicode char with ' (osh is more strict) |
375 |
|
376 |
# the mu character is U+03BC |
377 |
|
378 |
printf '%x\n' \'μ |
379 |
|
380 |
## STDOUT: |
381 |
3bc |
382 |
## END |
383 |
## BUG dash/mksh/ash STDOUT: |
384 |
ce |
385 |
## END |
386 |
|
387 |
#### negative numbers with unsigned / octal / hex |
388 |
printf '[%u]\n' -42 |
389 |
printf '[%o]\n' -42 |
390 |
printf '[%x]\n' -42 |
391 |
printf '[%X]\n' -42 |
392 |
## STDOUT: |
393 |
[18446744073709551574] |
394 |
[1777777777777777777726] |
395 |
[ffffffffffffffd6] |
396 |
[FFFFFFFFFFFFFFD6] |
397 |
## END |
398 |
|
399 |
# osh DISALLOWS this because the output depends on the machine architecture. |
400 |
## N-I osh stdout-json: "" |
401 |
## N-I osh status: 1 |
402 |
|
403 |
#### printf floating point (not required, but they all implement it) |
404 |
printf '[%f]\n' 3.14159 |
405 |
printf '[%.2f]\n' 3.14159 |
406 |
printf '[%8.2f]\n' 3.14159 |
407 |
printf '[%-8.2f]\n' 3.14159 |
408 |
printf '[%-f]\n' 3.14159 |
409 |
printf '[%-f]\n' 3.14 |
410 |
## STDOUT: |
411 |
[3.141590] |
412 |
[3.14] |
413 |
[ 3.14] |
414 |
[3.14 ] |
415 |
[3.141590] |
416 |
[3.140000] |
417 |
## END |
418 |
## N-I osh stdout-json: "" |
419 |
## N-I osh status: 2 |
420 |
|
421 |
#### printf floating point with - and 0 |
422 |
printf '[%8.4f]\n' 3.14 |
423 |
printf '[%08.4f]\n' 3.14 |
424 |
printf '[%8.04f]\n' 3.14 # meaning less 0 |
425 |
printf '[%08.04f]\n' 3.14 |
426 |
echo --- |
427 |
# these all boil down to the same thing. The -, 8, and 4 are respected, but |
428 |
# none of the 0 are. |
429 |
printf '[%-8.4f]\n' 3.14 |
430 |
printf '[%-08.4f]\n' 3.14 |
431 |
printf '[%-8.04f]\n' 3.14 |
432 |
printf '[%-08.04f]\n' 3.14 |
433 |
## STDOUT: |
434 |
[ 3.1400] |
435 |
[003.1400] |
436 |
[ 3.1400] |
437 |
[003.1400] |
438 |
--- |
439 |
[3.1400 ] |
440 |
[3.1400 ] |
441 |
[3.1400 ] |
442 |
[3.1400 ] |
443 |
## END |
444 |
## N-I osh STDOUT: |
445 |
--- |
446 |
## END |
447 |
## N-I osh status: 2 |
448 |
|
449 |
#### printf eE fF gG |
450 |
printf '[%e]\n' 3.14 |
451 |
printf '[%E]\n' 3.14 |
452 |
printf '[%f]\n' 3.14 |
453 |
# bash is the only one that implements %F? Is it a synonym? |
454 |
#printf '[%F]\n' 3.14 |
455 |
printf '[%g]\n' 3.14 |
456 |
printf '[%G]\n' 3.14 |
457 |
## STDOUT: |
458 |
[3.140000e+00] |
459 |
[3.140000E+00] |
460 |
[3.140000] |
461 |
[3.14] |
462 |
[3.14] |
463 |
## END |
464 |
## N-I osh stdout-json: "" |
465 |
## N-I osh status: 2 |
466 |
|
467 |
#### printf backslash escapes |
468 |
argv.py "$(printf 'a\tb')" |
469 |
argv.py "$(printf '\xE2\x98\xA0')" |
470 |
argv.py "$(printf '\044e')" |
471 |
argv.py "$(printf '\0377')" # out of range |
472 |
## STDOUT: |
473 |
['a\tb'] |
474 |
['\xe2\x98\xa0'] |
475 |
['$e'] |
476 |
['\x1f7'] |
477 |
## END |
478 |
## N-I dash STDOUT: |
479 |
['a\tb'] |
480 |
['\\xE2\\x98\\xA0'] |
481 |
['$e'] |
482 |
['\x1f7'] |
483 |
## END |
484 |
|
485 |
#### printf octal backslash escapes |
486 |
argv.py "$(printf '\0377')" |
487 |
argv.py "$(printf '\377')" |
488 |
## STDOUT: |
489 |
['\x1f7'] |
490 |
['\xff'] |
491 |
## END |
492 |
|
493 |
#### printf unicode backslash escapes |
494 |
argv.py "$(printf '\u2620')" |
495 |
argv.py "$(printf '\U0000065f')" |
496 |
## STDOUT: |
497 |
['\xe2\x98\xa0'] |
498 |
['\xd9\x9f'] |
499 |
## END |
500 |
## N-I dash/ash STDOUT: |
501 |
['\\u2620'] |
502 |
['\\U0000065f'] |
503 |
## END |
504 |
|
505 |
#### printf invalid backslash escape (is ignored) |
506 |
printf '[\Z]\n' |
507 |
## STDOUT: |
508 |
[\Z] |
509 |
## END |
510 |
|
511 |
#### printf % escapes |
512 |
printf '[%%]\n' |
513 |
## STDOUT: |
514 |
[%] |
515 |
## END |
516 |
|
517 |
#### printf %b backslash escaping |
518 |
printf '[%s]\n' '\044' # escapes not evaluated |
519 |
printf '[%b]\n' '\044' # YES, escapes evaluated |
520 |
echo status=$? |
521 |
## STDOUT: |
522 |
[\044] |
523 |
[$] |
524 |
status=0 |
525 |
## END |
526 |
|
527 |
#### printf %b with \c early return |
528 |
printf '[%b]\n' 'ab\ncd\cxy' |
529 |
echo $? |
530 |
## STDOUT: |
531 |
[ab |
532 |
cd0 |
533 |
## END |
534 |
|
535 |
#### printf %c -- doesn't respect UTF-8! Bad. |
536 |
twomu=$'\u03bc\u03bc' |
537 |
printf '[%s]\n' "$twomu" |
538 |
printf '%c' "$twomu" | wc --bytes |
539 |
## STDOUT: |
540 |
[μμ] |
541 |
1 |
542 |
## END |
543 |
## N-I dash STDOUT: |
544 |
[$\u03bc\u03bc] |
545 |
1 |
546 |
## END |
547 |
## N-I ash STDOUT: |
548 |
[\u03bc\u03bc] |
549 |
1 |
550 |
## END |
551 |
## N-I osh STDOUT: |
552 |
[μμ] |
553 |
0 |
554 |
## END |
555 |
|
556 |
#### printf invalid format |
557 |
printf '%z' 42 |
558 |
echo status=$? |
559 |
printf '%-z' 42 |
560 |
echo status=$? |
561 |
## STDOUT: |
562 |
status=1 |
563 |
status=1 |
564 |
## END |
565 |
# osh emits parse errors |
566 |
## OK dash/osh STDOUT: |
567 |
status=2 |
568 |
status=2 |
569 |
## END |
570 |
|
571 |
#### printf %q |
572 |
x='a b' |
573 |
printf '[%q]\n' "$x" |
574 |
## STDOUT: |
575 |
['a b'] |
576 |
## END |
577 |
## OK bash/zsh STDOUT: |
578 |
[a\ b] |
579 |
## END |
580 |
## N-I ash/dash stdout-json: "[" |
581 |
## N-I ash status: 1 |
582 |
## N-I dash status: 2 |
583 |
|
584 |
#### printf %6q (width) |
585 |
# NOTE: coreutils /usr/bin/printf does NOT implement this %6q !!! |
586 |
x='a b' |
587 |
printf '[%6q]\n' "$x" |
588 |
printf '[%1q]\n' "$x" |
589 |
## STDOUT: |
590 |
[ 'a b'] |
591 |
['a b'] |
592 |
## END |
593 |
## OK bash/zsh STDOUT: |
594 |
[ a\ b] |
595 |
[a\ b] |
596 |
## END |
597 |
## N-I mksh/ash/dash stdout-json: "[[" |
598 |
## N-I mksh/ash status: 1 |
599 |
## N-I dash status: 2 |
600 |
|
601 |
#### printf negative numbers |
602 |
printf '[%d] ' -42 |
603 |
echo status=$? |
604 |
printf '[%i] ' -42 |
605 |
echo status=$? |
606 |
|
607 |
# extra LEADING space too |
608 |
printf '[%d] ' ' -42' |
609 |
echo status=$? |
610 |
printf '[%i] ' ' -42' |
611 |
echo status=$? |
612 |
|
613 |
# extra TRAILING space too |
614 |
printf '[%d] ' ' -42 ' |
615 |
echo status=$? |
616 |
printf '[%i] ' ' -42 ' |
617 |
echo status=$? |
618 |
|
619 |
# extra TRAILING chars |
620 |
printf '[%d] ' ' -42z' |
621 |
echo status=$? |
622 |
printf '[%i] ' ' -42z' |
623 |
echo status=$? |
624 |
|
625 |
exit 0 # ok |
626 |
|
627 |
## STDOUT: |
628 |
[-42] status=0 |
629 |
[-42] status=0 |
630 |
[-42] status=0 |
631 |
[-42] status=0 |
632 |
[-42] status=1 |
633 |
[-42] status=1 |
634 |
[-42] status=1 |
635 |
[-42] status=1 |
636 |
## END |
637 |
# zsh is LESS STRICT |
638 |
## OK zsh STDOUT: |
639 |
[-42] status=0 |
640 |
[-42] status=0 |
641 |
[-42] status=0 |
642 |
[-42] status=0 |
643 |
[-42] status=0 |
644 |
[-42] status=0 |
645 |
[0] status=1 |
646 |
[0] status=1 |
647 |
## END |
648 |
|
649 |
# osh is like zsh but has a hard failure (TODO: could be an option?) |
650 |
## OK osh STDOUT: |
651 |
[-42] status=0 |
652 |
[-42] status=0 |
653 |
[-42] status=0 |
654 |
[-42] status=0 |
655 |
[-42] status=0 |
656 |
[-42] status=0 |
657 |
status=1 |
658 |
status=1 |
659 |
## END |
660 |
|
661 |
# ash is MORE STRICT |
662 |
## OK ash STDOUT: |
663 |
[-42] status=0 |
664 |
[-42] status=0 |
665 |
[-42] status=0 |
666 |
[-42] status=0 |
667 |
[0] status=1 |
668 |
[0] status=1 |
669 |
[0] status=1 |
670 |
[0] status=1 |
671 |
## END |
672 |
|
673 |
|
674 |
#### printf + and space flags |
675 |
# I didn't know these existed -- I only knew about - and 0 ! |
676 |
printf '[%+d]\n' 42 |
677 |
printf '[%+d]\n' -42 |
678 |
printf '[% d]\n' 42 |
679 |
printf '[% d]\n' -42 |
680 |
## STDOUT: |
681 |
[+42] |
682 |
[-42] |
683 |
[ 42] |
684 |
[-42] |
685 |
## END |
686 |
## N-I osh stdout-json: "" |
687 |
## N-I osh status: 2 |
688 |
|
689 |
#### printf # flag |
690 |
# I didn't know these existed -- I only knew about - and 0 ! |
691 |
# Note: '#' flag for integers outputs a prefix ONLY WHEN the value is non-zero |
692 |
printf '[%#o][%#o]\n' 0 42 |
693 |
printf '[%#x][%#x]\n' 0 42 |
694 |
printf '[%#X][%#X]\n' 0 42 |
695 |
echo --- |
696 |
# Note: '#' flag for %f, %g always outputs the decimal point. |
697 |
printf '[%.0f][%#.0f]\n' 3 3 |
698 |
# Note: In addition, '#' flag for %g does not omit zeroes in fraction |
699 |
printf '[%g][%#g]\n' 3 3 |
700 |
## STDOUT: |
701 |
[0][052] |
702 |
[0][0x2a] |
703 |
[0][0X2A] |
704 |
--- |
705 |
[3][3.] |
706 |
[3][3.00000] |
707 |
## END |
708 |
## N-I osh STDOUT: |
709 |
--- |
710 |
## END |
711 |
## N-I osh status: 2 |
712 |
|
713 |
#### Runtime error for invalid integer |
714 |
x=3abc |
715 |
printf '%d\n' $x |
716 |
echo status=$? |
717 |
printf '%d\n' xyz |
718 |
echo status=$? |
719 |
## STDOUT: |
720 |
3 |
721 |
status=1 |
722 |
0 |
723 |
status=1 |
724 |
## END |
725 |
# zsh should exit 1 in both cases |
726 |
## BUG zsh STDOUT: |
727 |
0 |
728 |
status=1 |
729 |
0 |
730 |
status=0 |
731 |
## END |
732 |
# fails but also prints 0 instead of 3abc |
733 |
## BUG ash STDOUT: |
734 |
0 |
735 |
status=1 |
736 |
0 |
737 |
status=1 |
738 |
## END |
739 |
# osh doesn't print anything invalid |
740 |
## OK osh STDOUT: |
741 |
status=1 |
742 |
status=1 |
743 |
## END |
744 |
|
745 |
#### %(strftime format)T |
746 |
# The result depends on timezone |
747 |
export TZ=Asia/Tokyo |
748 |
printf '%(%Y-%m-%d)T\n' 1557978599 |
749 |
export TZ=US/Eastern |
750 |
printf '%(%Y-%m-%d)T\n' 1557978599 |
751 |
echo status=$? |
752 |
## STDOUT: |
753 |
2019-05-16 |
754 |
2019-05-15 |
755 |
status=0 |
756 |
## END |
757 |
## N-I mksh/zsh/ash STDOUT: |
758 |
status=1 |
759 |
## END |
760 |
## N-I dash STDOUT: |
761 |
status=2 |
762 |
## END |
763 |
|
764 |
#### %(strftime format)T doesn't respect TZ if not exported |
765 |
|
766 |
# note: this test leaks! It assumes that /etc/localtime is NOT Portugal. |
767 |
|
768 |
TZ=Portugal # NOT exported |
769 |
localtime=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599) |
770 |
|
771 |
# TZ is respected |
772 |
export TZ=Portugal |
773 |
tz=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599) |
774 |
|
775 |
#echo $localtime |
776 |
#echo $tz |
777 |
|
778 |
if ! test "$localtime" = "$tz"; then |
779 |
echo 'not equal' |
780 |
fi |
781 |
## STDOUT: |
782 |
not equal |
783 |
## END |
784 |
## N-I mksh/zsh/ash/dash stdout-json: "" |
785 |
|
786 |
#### %(strftime format)T TZ in environ but not in shell's memory |
787 |
|
788 |
# note: this test leaks! It assumes that /etc/localtime is NOT Portugal. |
789 |
|
790 |
# TZ is respected |
791 |
export TZ=Portugal |
792 |
tz=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599) |
793 |
|
794 |
unset TZ # unset in the shell, but still in the environment |
795 |
|
796 |
localtime=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599) |
797 |
|
798 |
if ! test "$localtime" = "$tz"; then |
799 |
echo 'not equal' |
800 |
fi |
801 |
|
802 |
## STDOUT: |
803 |
not equal |
804 |
## END |
805 |
## N-I mksh/zsh/ash/dash stdout-json: "" |
806 |
|
807 |
#### %10.5(strftime format)T |
808 |
# The result depends on timezone |
809 |
export TZ=Asia/Tokyo |
810 |
printf '[%10.5(%Y-%m-%d)T]\n' 1557978599 |
811 |
export TZ=US/Eastern |
812 |
printf '[%10.5(%Y-%m-%d)T]\n' 1557978599 |
813 |
echo status=$? |
814 |
## STDOUT: |
815 |
[ 2019-] |
816 |
[ 2019-] |
817 |
status=0 |
818 |
## END |
819 |
## N-I dash/mksh/zsh/ash STDOUT: |
820 |
[[status=1 |
821 |
## END |
822 |
## N-I dash STDOUT: |
823 |
[[status=2 |
824 |
## END |
825 |
|
826 |
#### Regression for 'printf x y' |
827 |
printf x y |
828 |
printf '%s\n' z |
829 |
## STDOUT: |
830 |
xz |
831 |
## END |
832 |
|
833 |
#### bash truncates long strftime string at 128 |
834 |
|
835 |
case $SH in (ash|dash|mksh|zsh) exit ;; esac |
836 |
|
837 |
strftime-format() { |
838 |
local n=$1 |
839 |
|
840 |
# Prints increasingly long format strings: |
841 |
# %(%Y)T %(%Y)T %(%Y%Y)T ... |
842 |
|
843 |
echo -n '%(' |
844 |
for i in $(seq $n); do |
845 |
echo -n '%Y' |
846 |
done |
847 |
echo -n ')T' |
848 |
} |
849 |
|
850 |
printf $(strftime-format 1) | wc --bytes |
851 |
printf $(strftime-format 10) | wc --bytes |
852 |
printf $(strftime-format 30) | wc --bytes |
853 |
printf $(strftime-format 31) | wc --bytes |
854 |
printf $(strftime-format 32) | wc --bytes |
855 |
|
856 |
case $SH in |
857 |
(*/_bin/cxx-dbg/*) |
858 |
# Ensure that oil-native detects the truncation of a fixed buffer. |
859 |
# bash has a buffer of 128. |
860 |
|
861 |
set +o errexit |
862 |
( |
863 |
printf $(strftime-format 1000) |
864 |
) |
865 |
status=$? |
866 |
if test $status -ne 1; then |
867 |
echo FAIL |
868 |
fi |
869 |
;; |
870 |
esac |
871 |
|
872 |
## STDOUT: |
873 |
4 |
874 |
40 |
875 |
120 |
876 |
124 |
877 |
0 |
878 |
## END |
879 |
## OK osh STDOUT: |
880 |
4 |
881 |
40 |
882 |
120 |
883 |
124 |
884 |
128 |
885 |
## END |
886 |
|
887 |
## N-I ash/dash/mksh/zsh STDOUT: |
888 |
## END |
889 |
|
890 |
|
891 |
#### printf with explicit NUL byte |
892 |
case $SH in (dash|ash) return ;; esac |
893 |
|
894 |
printf $'x\U0z' |
895 |
|
896 |
printf $'\U0z' |
897 |
|
898 |
## stdout-json: "x" |
899 |
## OK zsh stdout-repr: "x\0z\0z" |
900 |
## N-I dash/ash stdout-json: "" |