1 #!/usr/bin/env bash
2
3 ### Here string
4 cat <<< 'hi'
5 # stdout-json: "hi\n"
6 # N-I dash stdout-json: ""
7 # N-I dash status: 2
8
9 ### Here string with $
10 cat <<< $'one\ntwo\n'
11 # stdout-json: "one\ntwo\n\n"
12 # N-I dash stdout-json: ""
13 # N-I dash status: 2
14
15 ### Here redirect with explicit descriptor
16 # A space betwen 0 and <<EOF causes it to pass '0' as an arg to cat.
17 cat 0<<EOF
18 one
19 EOF
20 # stdout: one
21
22 ### Here doc from another input file descriptor
23 # NOTE: OSH fails on descriptor 9, but not descriptor 8? Is this because of
24 # the Python VM? How to inspect state?
25 read_from_fd.py 8 8<<EOF
26 here doc on descriptor
27 EOF
28 # stdout: 8: here doc on descriptor
29
30 ### Multiple here docs with different descriptors
31 read_from_fd.py 0 3 <<EOF 3<<EOF3
32 fd0
33 EOF
34 fd3
35 EOF3
36 ## STDOUT:
37 0: fd0
38 3: fd3
39 ## END
40
41 ### Here doc with bad var delimiter
42 cat <<${a}
43 here
44 ${a}
45 # stdout: here
46
47 ### Here doc with bad comsub delimiter
48 # bash is OK with this; dash isn't. Should be a parse error.
49 cat <<$(a)
50 here
51 $(a)
52 # stdout-json: ""
53 # status: 2
54 # BUG bash stdout: here
55 # BUG bash status: 0
56 # OK mksh status: 1
57
58 ### Here doc and < redirect -- last one wins
59 echo hello >$TMP/hello.txt # temporary fix
60 cat <<EOF <$TMP/hello.txt
61 here
62 EOF
63 # stdout: hello
64
65 ### < redirect and here doc -- last one wins
66 cat <$TMP/hello.txt <<EOF
67 here
68 EOF
69 # stdout: here
70
71 ### Here doc with var sub, command sub, arith sub
72 var=v
73 cat <<EOF
74 var: ${var}
75 command: $(echo hi)
76 arith: $((1+2))
77 EOF
78 ## STDOUT:
79 var: v
80 command: hi
81 arith: 3
82 ## END
83
84 ### Here doc in middle. And redirects in the middle.
85 # This isn't specified by the POSIX grammar, but it's accepted by both dash and
86 # bash!
87 echo foo > _tmp/foo.txt
88 echo bar > _tmp/bar.txt
89 cat <<EOF 1>&2 _tmp/foo.txt - _tmp/bar.txt
90 here
91 EOF
92 ## STDERR:
93 foo
94 here
95 bar
96 ## END
97
98 ### Here doc line continuation
99 cat <<EOF \
100 ; echo two
101 one
102 EOF
103 ## STDOUT:
104 one
105 two
106 ## END
107
108 ### Here doc with quote expansion in terminator
109 cat <<'EOF'"2"
110 one
111 two
112 EOF2
113 # stdout-json: "one\ntwo\n"
114
115 ### Here doc with multiline double quoted string
116 cat <<EOF; echo "two
117 three"
118 one
119 EOF
120 ## STDOUT:
121 one
122 two
123 three
124 ## END
125
126 ### Two here docs -- first is ignored; second ones wins!
127 <<EOF1 cat <<EOF2
128 hello
129 EOF1
130 there
131 EOF2
132 # stdout: there
133
134 ### Here doc with line continuation, then pipe. Syntax error.
135 cat <<EOF \
136 1
137 2
138 3
139 EOF
140 | tac
141 # status: 2
142 # OK mksh status: 1
143
144 ### Here doc with pipe on first line
145 cat <<EOF | tac
146 1
147 2
148 3
149 EOF
150 ## STDOUT:
151 3
152 2
153 1
154 ## END
155
156 ### Here doc with pipe continued on last line
157 cat <<EOF |
158 1
159 2
160 3
161 EOF
162 tac
163 ## STDOUT:
164 3
165 2
166 1
167 ## END
168
169 ### Here doc with builtin 'read'
170 # read can't be run in a subshell.
171 read v1 v2 <<EOF
172 val1 val2
173 EOF
174 echo =$v1= =$v2=
175 # stdout: =val1= =val2=
176
177 ### Compound command here doc
178 while read line; do
179 echo X $line
180 done <<EOF
181 1
182 2
183 3
184 EOF
185 ## STDOUT:
186 X 1
187 X 2
188 X 3
189 ## END
190
191
192 ### Here doc in while condition and here doc in body
193 while cat <<E1 && cat <<E2; do cat <<E3; break; done
194 1
195 E1
196 2
197 E2
198 3
199 E3
200 ## STDOUT:
201 1
202 2
203 3
204 ## END
205
206 ### Here doc in while condition and here doc in body on multiple lines
207 while cat <<E1 && cat <<E2
208 1
209 E1
210 2
211 E2
212 do
213 cat <<E3
214 3
215 E3
216 break
217 done
218 ## STDOUT:
219 1
220 2
221 3
222 ## END
223
224 ### Here doc in while loop split up more
225 while cat <<E1
226 1
227 E1
228
229 cat <<E2
230 2
231 E2
232
233 do
234 cat <<E3
235 3
236 E3
237 break
238 done
239 ## STDOUT:
240 1
241 2
242 3
243 ## END
244
245 ### Mixing << and <<-
246 cat <<-EOF; echo --; cat <<EOF2
247 one
248 EOF
249 two
250 EOF2
251 # stdout-json: "one\n--\ntwo\n"
252
253
254
255 ### Two compound commands with two here docs
256 while read line; do echo X $line; done <<EOF; echo ==; while read line; do echo Y $line; done <<EOF2
257 1
258 2
259 EOF
260 3
261 4
262 EOF2
263 # stdout-json: "X 1\nX 2\n==\nY 3\nY 4\n"
264
265 ### Function def and execution with here doc
266 func() { cat; } <<EOF; echo before; func; echo after
267 1
268 2
269 EOF
270 # stdout-json: "before\n1\n2\nafter\n"
271
272 ### Here doc as command prefix
273 <<EOF tac
274 1
275 2
276 3
277 EOF
278 # stdout-json: "3\n2\n1\n"
279
280 # NOTE that you can have redirection AFTER the here doc thing. And you don't
281 # need a space! Those are operators.
282 #
283 # POSIX doesn't seem to have this? They have io_file, which is for
284 # filenames, and io_here, which is here doc. But about 1>&2 syntax? Geez.
285 ### Redirect after here doc
286 cat <<EOF 1>&2
287 out
288 EOF
289 # stderr: out
290
291 ### here doc stripping tabs
292 cat <<-EOF
293 1
294 2
295 3
296 EOF
297 ## STDOUT:
298 1
299 2
300 3
301 ## END
302
303 ### Here doc within subshell with boolean
304 [[ $(cat <<EOF
305 foo
306 EOF
307 ) == foo ]]; echo $?
308 # stdout: 0
309 # N-I dash stdout: 127
310
311 ### Here Doc in if condition
312 if cat <<EOF; then
313 here doc in IF CONDITION
314 EOF
315 echo THEN executed
316 fi
317 ## STDOUT:
318 here doc in IF CONDITION
319 THEN executed
320 ## END
321
322 ### Multiple here docs in pipeline
323 # SKIPPED: hangs with osh on Debian
324 # The second instance reads its stdin from the pipe, and fd 5 from a here doc.
325 read_from_fd.py 3 3<<EOF3 | read_from_fd.py 0 5 5<<EOF5
326 fd3
327 EOF3
328 fd5
329 EOF5
330 ## STDOUT:
331 0: 3: fd3
332 5: fd5
333 ## END
334
335 ### Multiple here docs in pipeline on multiple lines
336 # SKIPPED: hangs with osh on Debian
337 # The second instance reads its stdin from the pipe, and fd 5 from a here doc.
338 read_from_fd.py 3 3<<EOF3 |
339 fd3
340 EOF3
341 read_from_fd.py 0 5 5<<EOF5
342 fd5
343 EOF5
344 ## STDOUT:
345 0: 3: fd3
346 5: fd5
347 ## END