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