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