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