OILS / spec / command-sub.test.sh View on Github | oils.pub

299 lines, 75 significant
1## compare_shells: dash bash mksh
2
3#### case
4foo=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.
12echo $(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."
17foo=FOO; echo $(echo $foo)bar$(echo $foo)
18## stdout: FOObarFOO
19
20#### Backtick
21foo=FOO; echo `echo $foo`bar`echo $foo`
22## stdout: FOObarFOO
23
24#### Backtick 2
25echo `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!
31echo X > $TMP/000000-first
32echo `\`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
42echo status=$?
43## stdout-json: ""
44## status: 2
45## OK mksh status: 1
46
47#### Command sub with here doc
48echo $(<<EOF tac
49one
50two
51EOF
52)
53## stdout: two one
54
55#### Here doc with pipeline
56<<EOF tac | tr '\n' 'X'
57one
58two
59EOF
60## stdout-json: "twoXoneX"
61
62#### Command Sub word split
63argv.py $(echo 'hi there') "$(echo 'hi there')"
64## stdout: ['hi', 'there', 'hi there']
65
66#### Command Sub trailing newline removed
67s=$(python2 -c 'print("ab\ncd\n")')
68argv.py "$s"
69## stdout: ['ab\ncd']
70
71#### Command Sub trailing whitespace not removed
72s=$(python2 -c 'print("ab\ncd\n ")')
73argv.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.
78echo $(echo x; exit 33)
79echo $?
80x=$(echo x; exit 33)
81echo $?
82## STDOUT:
83x
840
8533
86## END
87
88#### Command Sub in local sets exit code
89# A command resets the exit code, but an assignment doesn't.
90f() {
91 echo $(echo x; exit 33)
92 echo $?
93 local x=$(echo x; exit 33)
94 echo $?
95}
96f
97## STDOUT:
98x
990
1000
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!
108echo "x $(echo hi)"
109echo "x $(echo "hi")"
110echo "x $(echo \"hi\")"
111echo "x `echo hi`"
112echo "x `echo "hi"`"
113echo "x `echo \"hi\"`"
114## STDOUT:
115x hi
116x hi
117x "hi"
118x hi
119x hi
120x hi
121## END
122
123#### Escaped quote in [[ ]]
124file=$TMP/command-sub-dbracket
125#rm -f $file
126echo "123 `[[ $(echo \\" > $file) ]]` 456";
127cat $file
128## STDOUT:
129123 456
130"
131## END
132
133#### Quoting " within ``
134echo 1 `echo \"`
135#echo 2 `echo \\"`
136#echo 3 `echo \\\"`
137#echo 4 `echo \\\\"`
138
139## STDOUT:
1401 "
141## END
142
143#### Quoting $ within ``
144echo 1 `echo $`
145echo 2 `echo \$`
146echo 3 `echo \\$`
147echo 4 `echo \\\$`
148echo 5 `echo \\\\$`
149## STDOUT:
1501 $
1512 $
1523 $
1534 $
1545 \$
155## END
156
157#### Quoting $ within `` within double quotes
158echo "1 `echo $`"
159echo "2 `echo \$`"
160echo "3 `echo \\$`"
161echo "4 `echo \\\$`"
162echo "5 `echo \\\\$`"
163## STDOUT:
1641 $
1652 $
1663 $
1674 $
1685 \$
169## END
170
171#### Quoting \ within ``
172# You need FOUR backslashes to make a literal \.
173echo [1 `echo \ `]
174echo [2 `echo \\ `]
175echo [3 `echo \\\\ `]
176## STDOUT:
177[1 ]
178[2 ]
179[3 \]
180## END
181
182#### Quoting \ within `` within double quotes
183echo "[1 `echo \ `]"
184echo "[2 `echo \\ `]"
185echo "[3 `echo \\\\ `]"
186## STDOUT:
187[1 ]
188[2 ]
189[3 \]
190## END
191
192#### Quoting ( within ``
193echo 1 `echo \(`
194echo 2 `echo \\(`
195echo 3 `echo \\ \\(`
196## STDOUT:
1971 (
1982 (
1993 (
200## END
201
202#### Quoting ( within `` within double quotes
203echo "1 `echo \(`"
204echo "2 `echo \\(`"
205echo "3 `echo \\ \\(`"
206## STDOUT:
2071 (
2082 (
2093 (
210## END
211
212#### Quoting non-special characters within ``
213echo [1 `echo \z]`
214echo [2 `echo \\z]`
215echo [3 `echo \\\z]`
216echo [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
225echo "[1 `echo \z`]"
226echo "[2 `echo \\z`]"
227echo "[3 `echo \\\z`]"
228echo "[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
237echo \"foo\" # for comparison
238echo `echo \"foo\"`
239echo `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
254echo `echo \\\"foo\\\"` -
255echo `echo \\\\"foo\\\\"` -
256echo `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 "`'
271echo status=$?
272$SH -c 'echo `echo \\\\"`'
273echo status=$?
274
275## STDOUT:
276status=2
277status=2
278## END
279## OK mksh STDOUT:
280status=1
281status=1
282## END
283## OK bash STDOUT:
284
285status=0
286
287status=0
288## END
289
290
291#### Empty command sub $() (command::NoOp)
292
293# IMPORTANT: catch assert() failure in child process!!!
294shopt -s command_sub_errexit
295
296echo -$()- ".$()."
297## STDOUT:
298-- ..
299## END