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