1
2 #### case
3 foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac
4 ## stdout: letter
5
6 #### case in subshell
7 # Hm this subhell has to know about the closing ) and stuff like that.
8 # case_clause is a compound_command, which is a command. And a subshell
9 # takes a compound_list, which is a list of terms, which has and_ors in them
10 # ... which eventually boils down to a command.
11 echo $(foo=a; case $foo in [0-9]) echo number;; [a-z]) echo letter;; esac)
12 ## stdout: letter
13
14 #### Command sub word part
15 # "The token shall not be delimited by the end of the substitution."
16 foo=FOO; echo $(echo $foo)bar$(echo $foo)
17 ## stdout: FOObarFOO
18
19 #### Backtick
20 foo=FOO; echo `echo $foo`bar`echo $foo`
21 ## stdout: FOObarFOO
22
23 #### Backtick 2
24 echo `echo -n l; echo -n s`
25 ## stdout: ls
26
27 #### Nested backticks
28 # Inner `` are escaped! Not sure how to do triple.. Seems like an unlikely
29 # use case. Not sure if I even want to support this!
30 echo X > $TMP/000000-first
31 echo `\`echo -n l; echo -n s\` $TMP | grep 000000-first`
32 ## stdout: 000000-first
33
34 #### Making command out of command sub should work
35 # Works in bash and dash!
36 $(echo ec)$(echo ho) split builtin
37 ## stdout: split builtin
38
39 #### Making keyword out of command sub should NOT work
40 $(echo f)$(echo or) i in a b c; do echo $i; done
41 echo status=$?
42 ## stdout-json: ""
43 ## status: 2
44 ## OK mksh status: 1
45
46 #### Command sub with here doc
47 echo $(<<EOF tac
48 one
49 two
50 EOF
51 )
52 ## stdout: two one
53
54 #### Here doc with pipeline
55 <<EOF tac | tr '\n' 'X'
56 one
57 two
58 EOF
59 ## stdout-json: "twoXoneX"
60
61 #### Command Sub word split
62 argv.py $(echo 'hi there') "$(echo 'hi there')"
63 ## stdout: ['hi', 'there', 'hi there']
64
65 #### Command Sub trailing newline removed
66 s=$(python2 -c 'print("ab\ncd\n")')
67 argv.py "$s"
68 ## stdout: ['ab\ncd']
69
70 #### Command Sub trailing whitespace not removed
71 s=$(python2 -c 'print("ab\ncd\n ")')
72 argv.py "$s"
73 ## stdout: ['ab\ncd\n ']
74
75 #### Command Sub and exit code
76 # A command resets the exit code, but an assignment doesn't.
77 echo $(echo x; exit 33)
78 echo $?
79 x=$(echo x; exit 33)
80 echo $?
81 ## STDOUT:
82 x
83 0
84 33
85 ## END
86
87 #### Command Sub in local sets exit code
88 # A command resets the exit code, but an assignment doesn't.
89 f() {
90 echo $(echo x; exit 33)
91 echo $?
92 local x=$(echo x; exit 33)
93 echo $?
94 }
95 f
96 ## STDOUT:
97 x
98 0
99 0
100 ## END
101
102 #### Double Quotes in Command Sub in Double Quotes
103 # virtualenv's bin/activate uses this.
104 # This is weird! Double quotes within `` is different than double quotes
105 # within $()! All shells agree.
106 # I think this is related to the nested backticks case!
107 echo "x $(echo hi)"
108 echo "x $(echo "hi")"
109 echo "x $(echo \"hi\")"
110 echo "x `echo hi`"
111 echo "x `echo "hi"`"
112 echo "x `echo \"hi\"`"
113 ## STDOUT:
114 x hi
115 x hi
116 x "hi"
117 x hi
118 x hi
119 x hi
120 ## END
121
122 #### Escaped quote in [[ ]]
123 file=$TMP/command-sub-dbracket
124 #rm -f $file
125 echo "123 `[[ $(echo \\" > $file) ]]` 456";
126 cat $file
127 ## STDOUT:
128 123 456
129 "
130 ## END
131
132 #### Quoting " within ``
133 echo 1 `echo \"`
134 #echo 2 `echo \\"`
135 #echo 3 `echo \\\"`
136 #echo 4 `echo \\\\"`
137
138 ## STDOUT:
139 1 "
140 ## END
141
142 #### Quoting $ within ``
143 echo 1 `echo $`
144 echo 2 `echo \$`
145 echo 3 `echo \\$`
146 echo 4 `echo \\\$`
147 echo 5 `echo \\\\$`
148 ## STDOUT:
149 1 $
150 2 $
151 3 $
152 4 $
153 5 \$
154 ## END
155
156 #### Quoting $ within `` within double quotes
157 echo "1 `echo $`"
158 echo "2 `echo \$`"
159 echo "3 `echo \\$`"
160 echo "4 `echo \\\$`"
161 echo "5 `echo \\\\$`"
162 ## STDOUT:
163 1 $
164 2 $
165 3 $
166 4 $
167 5 \$
168 ## END
169
170 #### Quoting \ within ``
171 # You need FOUR backslashes to make a literal \.
172 echo [1 `echo \ `]
173 echo [2 `echo \\ `]
174 echo [3 `echo \\\\ `]
175 ## STDOUT:
176 [1 ]
177 [2 ]
178 [3 \]
179 ## END
180
181 #### Quoting \ within `` within double quotes
182 echo "[1 `echo \ `]"
183 echo "[2 `echo \\ `]"
184 echo "[3 `echo \\\\ `]"
185 ## STDOUT:
186 [1 ]
187 [2 ]
188 [3 \]
189 ## END
190
191 #### Quoting ( within ``
192 echo 1 `echo \(`
193 echo 2 `echo \\(`
194 echo 3 `echo \\ \\(`
195 ## STDOUT:
196 1 (
197 2 (
198 3 (
199 ## END
200
201 #### Quoting ( within `` within double quotes
202 echo "1 `echo \(`"
203 echo "2 `echo \\(`"
204 echo "3 `echo \\ \\(`"
205 ## STDOUT:
206 1 (
207 2 (
208 3 (
209 ## END
210
211 #### Quoting non-special characters within ``
212 echo [1 `echo \z]`
213 echo [2 `echo \\z]`
214 echo [3 `echo \\\z]`
215 echo [4 `echo \\\\z]`
216 ## STDOUT:
217 [1 z]
218 [2 z]
219 [3 \z]
220 [4 \z]
221 ## END
222
223 #### Quoting non-special characters within `` within double quotes
224 echo "[1 `echo \z`]"
225 echo "[2 `echo \\z`]"
226 echo "[3 `echo \\\z`]"
227 echo "[4 `echo \\\\z`]"
228 ## STDOUT:
229 [1 z]
230 [2 z]
231 [3 \z]
232 [4 \z]
233 ## END
234
235 #### Quoting double quotes within backticks
236 echo \"foo\" # for comparison
237 echo `echo \"foo\"`
238 echo `echo \\"foo\\"`
239 ## STDOUT:
240 "foo"
241 "foo"
242 "foo"
243 ## END
244
245 #### More levels of double quotes in backticks
246 # Shells don't agree here, some of them give you form feeds!
247 # There are two levels of processing I don't understand.
248 echo BUG
249 exit
250 echo `echo \\\"foo\\\"`
251 echo `echo \\\\"foo\\\\"`
252 echo `echo \\\\\"foo\\\\\"`
253 ## BUG bash/dash/mksh/osh STDOUT:
254 BUG
255 ## END
256
257 #### Syntax errors with double quotes within backticks
258
259 # bash does print syntax errors but somehow it exits 0
260
261 $SH -c 'echo `echo "`'
262 echo status=$?
263 $SH -c 'echo `echo \\\\"`'
264 echo status=$?
265
266 ## STDOUT:
267 status=2
268 status=2
269 ## END
270 ## OK mksh STDOUT:
271 status=1
272 status=1
273 ## END
274 ## OK bash stdout-json: "\nstatus=0\n\nstatus=0\n"
275
276
277 #### Empty command sub $() (command::NoOp)
278
279 # IMPORTANT: catch assert() failure in child process!!!
280 shopt -s command_sub_errexit
281
282 echo -$()- ".$()."
283 ## STDOUT:
284 -- ..
285 ## END