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=$(python -c 'print("ab\ncd\n")')
67 argv.py "$s"
68 ## stdout: ['ab\ncd']
69
70 #### Command Sub trailing whitespace not removed
71 s=$(python -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 echo 5 `echo \\\\$`
138 ## STDOUT:
139 1 $
140 2 $
141 3 $
142 4 $
143 5 \$
144 ## END
145
146 #### Quoting $ within `` within double quotes
147 echo "1 `echo $`"
148 echo "2 `echo \$`"
149 echo "3 `echo \\$`"
150 echo "4 `echo \\\$`"
151 echo "5 `echo \\\\$`"
152 ## STDOUT:
153 1 $
154 2 $
155 3 $
156 4 $
157 5 \$
158 ## END
159
160 #### Quoting \ within ``
161 # You need FOUR backslashes to make a literal \.
162 echo [1 `echo \ `]
163 echo [2 `echo \\ `]
164 echo [3 `echo \\\\ `]
165 ## STDOUT:
166 [1 ]
167 [2 ]
168 [3 \]
169 ## END
170
171 #### Quoting \ within `` within double quotes
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 ``
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 `` within double quotes
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 non-special characters within ``
202 echo [1 `echo \z]`
203 echo [2 `echo \\z]`
204 echo [3 `echo \\\z]`
205 echo [4 `echo \\\\z]`
206 ## STDOUT:
207 [1 z]
208 [2 z]
209 [3 \z]
210 [4 \z]
211 ## END
212
213 #### Quoting non-special characters within `` within double quotes
214 echo "[1 `echo \z`]"
215 echo "[2 `echo \\z`]"
216 echo "[3 `echo \\\z`]"
217 echo "[4 `echo \\\\z`]"
218 ## STDOUT:
219 [1 z]
220 [2 z]
221 [3 \z]
222 [4 \z]
223 ## END
224
225 #### Quoting double quotes within backticks
226 echo \"foo\" # for comparison
227 echo `echo \"foo\"`
228 echo `echo \\"foo\\"`
229 ## STDOUT:
230 "foo"
231 "foo"
232 "foo"
233 ## END
234
235 # Documented in doc/known-differences.md (and Morbig paper brought up the same
236 # issue)
237 ## OK osh STDOUT:
238 "foo"
239 foo
240 "foo"
241 ## END
242
243 #### More levels of double quotes in backticks
244 # Shells don't agree here, some of them give you form feeds!
245 # There are two levels of processing I don't understand.
246 echo BUG
247 exit
248 echo `echo \\\"foo\\\"`
249 echo `echo \\\\"foo\\\\"`
250 echo `echo \\\\\"foo\\\\\"`
251 ## BUG bash/dash/mksh/osh STDOUT:
252 BUG
253 ## END
254
255 #### Syntax errors with double quotes within backticks
256
257 # bash does print syntax errors but somehow it exits 0
258
259 $SH -c 'echo `echo "`'
260 echo status=$?
261 $SH -c 'echo `echo \\\\"`'
262 echo status=$?
263
264 ## STDOUT:
265 status=2
266 status=2
267 ## END
268 ## OK mksh STDOUT:
269 status=1
270 status=1
271 ## END
272 ## OK bash stdout-json: "\nstatus=0\n\nstatus=0\n"