1 #!/usr/bin/env bash
2
3 #### case
4 foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac
5 ## stdout: letter
6
7 #### case in subshell
8 # Hm this subhell has to know about the closing ) and stuff like that.
9 # case_clause is a compound_command, which is a command. And a subshell
10 # takes a compound_list, which is a list of terms, which has and_ors in them
11 # ... which eventually boils down to a command.
12 echo $(foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac)
13 ## stdout: letter
14
15 #### Command sub word part
16 # "The token shall not be delimited by the end of the substitution."
17 foo=FOO; echo $(echo $foo)bar$(echo $foo)
18 ## stdout: FOObarFOO
19
20 #### Backtick
21 foo=FOO; echo `echo $foo`bar`echo $foo`
22 ## stdout: FOObarFOO
23
24 #### Backtick 2
25 echo `echo -n l; echo -n s`
26 ## stdout: ls
27
28 #### Nested backticks
29 # Inner `` are escaped! # Not sure how to do triple.. Seems like an unlikely
30 # use case. Not sure if I even want to support this!
31 echo X > $TMP/000000-first
32 echo `\`echo -n l; echo -n s\` $TMP | grep 000000-first`
33 ## stdout: 000000-first
34
35 #### Making command out of command sub should work
36 # Works in bash and dash!
37 $(echo ec)$(echo ho) split builtin
38 ## stdout: split builtin
39
40 #### Making keyword out of command sub should NOT work
41 # This doesn't work in bash or dash! Hm builtins are different than keywords /
42 # reserved words I guess.
43 # dash fails, but gives code 0
44 $(echo f)$(echo or) i in a b c; do echo $i; done
45 echo status=$?
46 ## stdout-json: ""
47 ## status: 2
48 ## BUG dash stdout-json: "\nstatus=0\n"
49 ## BUG dash status: 0
50 ## OK mksh status: 1
51
52 #### Command sub with here doc
53 echo $(<<EOF tac
54 one
55 two
56 EOF
57 )
58 ## stdout: two one
59
60 #### Here doc with pipeline
61 <<EOF tac | tr '\n' 'X'
62 one
63 two
64 EOF
65 ## stdout-json: "twoXoneX"
66
67 #### Command Sub word split
68 argv.py $(echo 'hi there') "$(echo 'hi there')"
69 ## stdout: ['hi', 'there', 'hi there']
70
71 #### Command Sub trailing newline removed
72 s=$(python -c 'print "ab\ncd\n"')
73 argv.py "$s"
74 ## stdout: ['ab\ncd']
75
76 #### Command Sub trailing whitespace not removed
77 s=$(python -c 'print "ab\ncd\n "')
78 argv.py "$s"
79 ## stdout: ['ab\ncd\n ']
80
81 #### Command Sub and exit code
82 # A command resets the exit code, but an assignment doesn't.
83 echo $(echo x; exit 33)
84 echo $?
85 x=$(echo x; exit 33)
86 echo $?
87 ## STDOUT:
88 x
89 0
90 33
91 ## END
92
93 #### Command Sub in local sets exit code
94 # A command resets the exit code, but an assignment doesn't.
95 f() {
96 echo $(echo x; exit 33)
97 echo $?
98 local x=$(echo x; exit 33)
99 echo $?
100 }
101 f
102 ## STDOUT:
103 x
104 0
105 0
106 ## END