1 ## compare_shells: dash bash mksh
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 $(echo f)$(echo or) i in a b c; do echo $i; done
42 echo status=$?
43 ## stdout-json: ""
44 ## status: 2
45 ## OK mksh status: 1
46
47 #### Command sub with here doc
48 echo $(<<EOF tac
49 one
50 two
51 EOF
52 )
53 ## stdout: two one
54
55 #### Here doc with pipeline
56 <<EOF tac | tr '\n' 'X'
57 one
58 two
59 EOF
60 ## stdout-json: "twoXoneX"
61
62 #### Command Sub word split
63 argv.py $(echo 'hi there') "$(echo 'hi there')"
64 ## stdout: ['hi', 'there', 'hi there']
65
66 #### Command Sub trailing newline removed
67 s=$(python2 -c 'print("ab\ncd\n")')
68 argv.py "$s"
69 ## stdout: ['ab\ncd']
70
71 #### Command Sub trailing whitespace not removed
72 s=$(python2 -c 'print("ab\ncd\n ")')
73 argv.py "$s"
74 ## stdout: ['ab\ncd\n ']
75
76 #### Command Sub and exit code
77 # A command resets the exit code, but an assignment doesn't.
78 echo $(echo x; exit 33)
79 echo $?
80 x=$(echo x; exit 33)
81 echo $?
82 ## STDOUT:
83 x
84 0
85 33
86 ## END
87
88 #### Command Sub in local sets exit code
89 # A command resets the exit code, but an assignment doesn't.
90 f() {
91 echo $(echo x; exit 33)
92 echo $?
93 local x=$(echo x; exit 33)
94 echo $?
95 }
96 f
97 ## STDOUT:
98 x
99 0
100 0
101 ## END
102
103 #### Double Quotes in Command Sub in Double Quotes
104 # virtualenv's bin/activate uses this.
105 # This is weird! Double quotes within `` is different than double quotes
106 # within $()! All shells agree.
107 # I think this is related to the nested backticks case!
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 echo "x `echo \"hi\"`"
114 ## STDOUT:
115 x hi
116 x hi
117 x "hi"
118 x hi
119 x hi
120 x hi
121 ## END
122
123 #### Escaped quote in [[ ]]
124 file=$TMP/command-sub-dbracket
125 #rm -f $file
126 echo "123 `[[ $(echo \\" > $file) ]]` 456";
127 cat $file
128 ## STDOUT:
129 123 456
130 "
131 ## END
132
133 #### Quoting " within ``
134 echo 1 `echo \"`
135 #echo 2 `echo \\"`
136 #echo 3 `echo \\\"`
137 #echo 4 `echo \\\\"`
138
139 ## STDOUT:
140 1 "
141 ## END
142
143 #### Quoting $ within ``
144 echo 1 `echo $`
145 echo 2 `echo \$`
146 echo 3 `echo \\$`
147 echo 4 `echo \\\$`
148 echo 5 `echo \\\\$`
149 ## STDOUT:
150 1 $
151 2 $
152 3 $
153 4 $
154 5 \$
155 ## END
156
157 #### Quoting $ within `` within double quotes
158 echo "1 `echo $`"
159 echo "2 `echo \$`"
160 echo "3 `echo \\$`"
161 echo "4 `echo \\\$`"
162 echo "5 `echo \\\\$`"
163 ## STDOUT:
164 1 $
165 2 $
166 3 $
167 4 $
168 5 \$
169 ## END
170
171 #### Quoting \ within ``
172 # You need FOUR backslashes to make a literal \.
173 echo [1 `echo \ `]
174 echo [2 `echo \\ `]
175 echo [3 `echo \\\\ `]
176 ## STDOUT:
177 [1 ]
178 [2 ]
179 [3 \]
180 ## END
181
182 #### Quoting \ within `` within double quotes
183 echo "[1 `echo \ `]"
184 echo "[2 `echo \\ `]"
185 echo "[3 `echo \\\\ `]"
186 ## STDOUT:
187 [1 ]
188 [2 ]
189 [3 \]
190 ## END
191
192 #### Quoting ( within ``
193 echo 1 `echo \(`
194 echo 2 `echo \\(`
195 echo 3 `echo \\ \\(`
196 ## STDOUT:
197 1 (
198 2 (
199 3 (
200 ## END
201
202 #### Quoting ( within `` within double quotes
203 echo "1 `echo \(`"
204 echo "2 `echo \\(`"
205 echo "3 `echo \\ \\(`"
206 ## STDOUT:
207 1 (
208 2 (
209 3 (
210 ## END
211
212 #### Quoting non-special characters within ``
213 echo [1 `echo \z]`
214 echo [2 `echo \\z]`
215 echo [3 `echo \\\z]`
216 echo [4 `echo \\\\z]`
217 ## STDOUT:
218 [1 z]
219 [2 z]
220 [3 \z]
221 [4 \z]
222 ## END
223
224 #### Quoting non-special characters within `` within double quotes
225 echo "[1 `echo \z`]"
226 echo "[2 `echo \\z`]"
227 echo "[3 `echo \\\z`]"
228 echo "[4 `echo \\\\z`]"
229 ## STDOUT:
230 [1 z]
231 [2 z]
232 [3 \z]
233 [4 \z]
234 ## END
235
236 #### Quoting double quotes within backticks
237 echo \"foo\" # for comparison
238 echo `echo \"foo\"`
239 echo `echo \\"foo\\"`
240 ## STDOUT:
241 "foo"
242 "foo"
243 "foo"
244 ## END
245
246 #### More levels of double quotes in backticks
247
248 # Shells don't agree here, some of them give you form feeds!
249 # There are two levels of processing I don't understand.
250
251 #echo BUG
252 #exit
253
254 echo `echo \\\"foo\\\"` -
255 echo `echo \\\\"foo\\\\"` -
256 echo `echo \\\\\"foo\\\\\"` -
257
258 ## STDOUT:
259 \foo\ -
260 \foo\ -
261 \"foo\" -
262 ## END
263
264 ## BUG dash/mksh stdout-json: "\u000coo\\ -\n\u000coo\\ -\n\\\"foo\\\" -\n"
265
266 #### Syntax errors with double quotes within backticks
267
268 # bash does print syntax errors but somehow it exits 0
269
270 $SH -c 'echo `echo "`'
271 echo status=$?
272 $SH -c 'echo `echo \\\\"`'
273 echo status=$?
274
275 ## STDOUT:
276 status=2
277 status=2
278 ## END
279 ## OK mksh STDOUT:
280 status=1
281 status=1
282 ## END
283 ## OK bash STDOUT:
284
285 status=0
286
287 status=0
288 ## END
289
290
291 #### Empty command sub $() (command::NoOp)
292
293 # IMPORTANT: catch assert() failure in child process!!!
294 shopt -s command_sub_errexit
295
296 echo -$()- ".$()."
297 ## STDOUT:
298 -- ..
299 ## END