Here document: Difference between revisions
No edit summary |
No edit summary |
||
Line 8: | Line 8: | ||
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}} |
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}} |
||
Algol 68 does not have a "heredoc" feature. It can be crudely achieved using an array of strings: |
Algol 68 does not have a "heredoc" feature. It can be crudely achieved using an array of strings: |
||
<lang algol68>#!/usr/local/bin/a68g --script # |
|||
<lang algol68> |
|||
#!/usr/local/bin/a68g --script # |
|||
[]STRING help = ( |
[]STRING help = ( |
||
Line 24: | Line 26: | ||
"I've one thing to say and that's ...", |
"I've one thing to say and that's ...", |
||
"Dammit. Janet, I love you." |
"Dammit. Janet, I love you." |
||
)) |
)) |
||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Usage: thingy [OPTIONS] |
Usage: thingy [OPTIONS] |
||
Line 37: | Line 42: | ||
Dammit. Janet, I love you. |
Dammit. Janet, I love you. |
||
</pre> |
</pre> |
||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
AutoHotkey uses "continuation sections" for literal text: |
AutoHotkey uses "continuation sections" for literal text: |
||
<lang AutoHotkey>MyVar = "This is the text inside MyVar" |
|||
<lang AutoHotkey> |
|||
MyVar = "This is the text inside MyVar" |
|||
MyVariable = |
MyVariable = |
||
( |
( |
||
Line 47: | Line 55: | ||
Variable references such as %MyVar% are expanded. |
Variable references such as %MyVar% are expanded. |
||
) |
) |
||
MsgBox % MyVariable |
MsgBox % MyVariable |
||
</lang> |
|||
=={{header|C sharp}}== |
=={{header|C sharp}}== |
||
C# has a string literal call which is used for heredoc functionality |
C# has a string literal call which is used for heredoc functionality |
||
<lang C sharp> |
<lang C sharp> |
||
using System; |
|||
class Program |
class Program |
||
Line 64: | Line 74: | ||
in C#"); |
in C#"); |
||
} |
} |
||
} |
|||
}</lang> |
|||
</lang> |
|||
=={{header|CoffeeScript}}== |
=={{header|CoffeeScript}}== |
||
CoffeeScript borrows the triple-quoted string syntax from Python. Note that these strings strip leading whitespace in CoffeeScript, to allow you to neatly align the heredoc string. |
CoffeeScript borrows the triple-quoted string syntax from Python. Note that these strings strip leading whitespace in CoffeeScript, to allow you to neatly align the heredoc string. |
||
<lang coffeescript>myDoc = ''' |
|||
<lang coffeescript> |
|||
myDoc = ''' |
|||
Single-quoted heredocs allows no '#{foo}' interpolation. |
Single-quoted heredocs allows no '#{foo}' interpolation. |
||
This behavior is similar to single-quoted strings. |
This behavior is similar to single-quoted strings. |
||
Line 78: | Line 91: | ||
""" |
""" |
||
console.log doc2 |
console.log doc2 |
||
</lang> |
|||
The above would output the following: |
The above would output the following: |
||
<pre>However, double-quoted heredocs *do* allow these. |
|||
<pre> |
|||
However, double-quoted heredocs *do* allow these. |
|||
See it in action: |
See it in action: |
||
Content: "Single-quoted heredocs allows no '#{foo}' interpolation. |
Content: "Single-quoted heredocs allows no '#{foo}' interpolation. |
||
This behavior is similar to single-quoted strings." |
This behavior is similar to single-quoted strings." |
||
</pre> |
|||
Note how the extra indentation in the third line of doc2 is preserved. |
Note how the extra indentation in the third line of doc2 is preserved. |
||
Line 91: | Line 108: | ||
{{works with|D|2}} |
{{works with|D|2}} |
||
In D there are delimited strings: a 'q' followed by double quotes and an opening and closing delimiter of choice: |
In D there are delimited strings: a 'q' followed by double quotes and an opening and closing delimiter of choice: |
||
<lang d> |
|||
<lang d>auto s = q"[a string that you "don't" have to escape]";</lang> |
|||
auto s = q"[a string that you "don't" have to escape]"; |
|||
</lang> |
|||
If the delimiter is an identifier, the identifier must be immediately followed by a newline, and the matching delimiter is the same identifier starting at the beginning of the line: |
If the delimiter is an identifier, the identifier must be immediately followed by a newline, and the matching delimiter is the same identifier starting at the beginning of the line: |
||
<lang d> |
<lang d> |
||
writefln(q"EOS |
|||
This |
This |
||
is a multi-line |
is a multi-line |
||
heredoc string |
heredoc string |
||
EOS" |
EOS" |
||
); |
); |
||
</lang> |
|||
<pre> |
|||
<pre>a string you " " don't have to escape |
|||
a string you " " don't have to escape |
|||
This |
This |
||
is a multi-line |
is a multi-line |
||
heredoc string |
heredoc string |
||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Go does not have here documents. Multiline string literals serve this purpose. |
Go does not have here documents. Multiline string literals serve this purpose. |
||
<lang go>var m = ` leading spaces |
|||
<lang go> |
|||
var m = ` leading spaces |
|||
and blank lines` |
|||
=={{header|J}}== |
|||
</lang> |
|||
=={{header|J}}== |
|||
<lang j>here=:0 :0 |
|||
<lang j> |
|||
here=:0 :0 |
|||
0 :0 will be replaced by the text on the following lines. |
0 :0 will be replaced by the text on the following lines. |
||
This is three tokens: two instances of the number 0 and |
This is three tokens: two instances of the number 0 and |
||
Line 154: | Line 181: | ||
note that this mechanism is significantly more verbose than using |
note that this mechanism is significantly more verbose than using |
||
the underlying 0 :0 mechanism directly. |
the underlying 0 :0 mechanism directly. |
||
) |
|||
)</lang> |
|||
</lang> |
|||
=={{header|NMAKE.EXE}}== |
|||
<lang nmake.exe> |
|||
target0: dependent0 |
|||
command0 << |
|||
temporary, discarded inline file |
|||
... |
|||
<< |
|||
target1: dependent1 |
|||
command1 << |
|||
temporary, but preserved inline file |
|||
... |
|||
<<KEEP |
|||
target2: dependent2 |
|||
command2 <<filename2 |
|||
named, but discarded inline file |
|||
... |
|||
<<NOKEEP |
|||
target3: dependent3 |
|||
command3 <<filename3 |
|||
named and preserved inline file |
|||
... |
|||
<<KEEP |
|||
</lang> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
In Perl, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised. Interpolation is allowed, like a double-quoted string: |
In Perl, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised. Interpolation is allowed, like a double-quoted string: |
||
<lang perl> |
<lang perl> |
||
$address = <<END; |
|||
1, High Street, |
1, High Street, |
||
$town_name, |
$town_name, |
||
West Midlands. |
West Midlands. |
||
WM4 5HD. |
WM4 5HD. |
||
END |
END |
||
</lang> |
|||
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: |
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: |
||
<lang perl> |
<lang perl> |
||
$pancake = <<"NO MORE INGREDIENTS"; |
|||
egg |
egg |
||
milk |
milk |
||
flour |
flour |
||
NO MORE INGREDIENTS |
NO MORE INGREDIENTS |
||
</lang> |
|||
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string: |
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string: |
||
<lang perl> |
<lang perl> |
||
$x = <<'FOO'; |
|||
No |
No |
||
$interpolation |
$interpolation |
||
here |
here |
||
FOO |
FOO |
||
</lang> |
|||
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator: |
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator: |
||
<lang perl> |
<lang perl> |
||
$output = <<`BAR`; |
|||
ls /home |
ls /home |
||
BAR |
BAR |
||
</lang> |
|||
Note that in the above examples, that a semicolon was left after the here document's token string. This is because (unlike PHP) the here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression: |
Note that in the above examples, that a semicolon was left after the here document's token string. This is because (unlike PHP) the here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression: |
||
<lang perl> |
<lang perl> |
||
print(<<EOF . "lamb\n"); |
|||
Mary had |
Mary had |
||
a little |
a little |
||
EOF |
EOF |
||
</lang> |
|||
Although, technically speaking, it is also possible to break a statement into two parts, with the here document in the middle (i.e. continue the statement on the line after the terminating token). However, please don't do this. |
Although, technically speaking, it is also possible to break a statement into two parts, with the here document in the middle (i.e. continue the statement on the line after the terminating token). However, please don't do this. |
||
<lang perl> |
<lang perl> |
||
print(<<EOF |
|||
Mary had |
Mary had |
||
a little |
a little |
||
EOF |
EOF |
||
. "lamb\n"); |
. "lamb\n"); |
||
</lang> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |
||
Heredocs in Perl 6 use the <code>:to</code> modifier to a quoting operator, such as <code>q</code> or <code>qq</code>. Multiple here docs may be stacked on top of each other. |
Heredocs in Perl 6 use the <code>:to</code> modifier to a quoting operator, such as <code>q</code> or <code>qq</code>. Multiple here docs may be stacked on top of each other. |
||
{{works with|niecza}} |
{{works with|niecza}} |
||
<lang perl6> |
<lang perl6> |
||
my $contrived_example = 'Dylan'; |
|||
sub freewheelin() { |
sub freewheelin() { |
||
print q :to 'QUOTE', '-- ', qq :to 'AUTHOR'; |
print q :to 'QUOTE', '-- ', qq :to 'AUTHOR'; |
||
Line 221: | Line 288: | ||
Output: |
Output: |
||
<pre> |
|||
<pre> I'll let you be in my dream, |
|||
I'll let you be in my dream, |
|||
if I can be in yours. |
if I can be in yours. |
||
-- Bob Dylan |
-- Bob Dylan |
||
</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
Line 230: | Line 299: | ||
There must not be a space between the "<<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, except for a possible semicolon. Interpolation is allowed, like a double-quoted string: |
There must not be a space between the "<<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, except for a possible semicolon. Interpolation is allowed, like a double-quoted string: |
||
<lang php> |
<lang php> |
||
$address = <<<END |
|||
1, High Street, |
1, High Street, |
||
$town_name, |
$town_name, |
||
West Midlands. |
West Midlands. |
||
WM4 5HD. |
WM4 5HD. |
||
END; |
END; |
||
</lang> |
|||
In PHP 5.3+, it is possible to make a here-document that does not interpolate (PHP calls this a "nowdoc"), by surrounding the token with single-quotes (like in Perl): |
In PHP 5.3+, it is possible to make a here-document that does not interpolate (PHP calls this a "nowdoc"), by surrounding the token with single-quotes (like in Perl): |
||
<lang php>$x = <<<'FOO' |
|||
<lang php> |
|||
$x = <<<'FOO' |
|||
No |
No |
||
$interpolation |
$interpolation |
||
here |
here |
||
FOO; |
FOO; |
||
</lang> |
|||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
We can use the '[http://software-lab.de/doc/refH.html#here here]' function: |
We can use the '[http://software-lab.de/doc/refH.html#here here]' function: |
||
<lang PicoLisp>(out "file.txt" # Write to "file.txt" |
|||
<lang PicoLisp> |
|||
(out "file.txt" # Write to "file.txt" |
|||
(prinl "### This is before the text ###") |
(prinl "### This is before the text ###") |
||
(here "TEXT-END") |
(here "TEXT-END") |
||
Line 254: | Line 330: | ||
TEXT-END |
TEXT-END |
||
(in "file.txt" (echo)) # Show "file.txt" |
(in "file.txt" (echo)) # Show "file.txt" |
||
</lang> |
|||
Output: |
Output: |
||
<pre>### This is before the text ### |
|||
<pre> |
|||
### This is before the text ### |
|||
"There must be some way out of here", said the joker to the thief |
"There must be some way out of here", said the joker to the thief |
||
"There's too much confusion, I can't get no relief" |
"There's too much confusion, I can't get no relief" |
||
### This is after the text ### |
### This is after the text ### |
||
</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
Python does not have here-docs. It does however have [http://docs.python.org/py3k/tutorial/introduction.html#strings triple-quoted strings] which can be used similarly. |
Python does not have here-docs. It does however have [http://docs.python.org/py3k/tutorial/introduction.html#strings triple-quoted strings] which can be used similarly. |
||
<lang python>print("""\ |
|||
<lang python> |
|||
print("""\ |
|||
Usage: thingy [OPTIONS] |
Usage: thingy [OPTIONS] |
||
-h Display this usage message |
-h Display this usage message |
||
-H hostname Hostname to connect to |
-H hostname Hostname to connect to |
||
""") |
""") |
||
</lang> |
|||
=={{header|Retro}}== |
=={{header|Retro}}== |
||
Line 276: | Line 360: | ||
a multi-line string |
a multi-line string |
||
with indention |
with indention |
||
and such" |
and such" |
||
</lang> |
|||
If you need an actual '''heredoc''' function, the following should suffice: |
If you need an actual '''heredoc''' function, the following should suffice: |
||
<lang Retro> |
<lang Retro> |
||
{{ |
|||
: getDelimiter ( "-$ ) |
: getDelimiter ( "-$ ) |
||
getToken keepString cr ; |
getToken keepString cr ; |
||
Line 304: | Line 390: | ||
In Ruby, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, unless you use "<<-" instead of "<<", in which case indentation before the ending token is allowed. Interpolation is allowed, like a double-quoted string: |
In Ruby, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, unless you use "<<-" instead of "<<", in which case indentation before the ending token is allowed. Interpolation is allowed, like a double-quoted string: |
||
<lang ruby> |
<lang ruby> |
||
address = <<END |
|||
1, High Street, |
1, High Street, |
||
#{town_name}, |
#{town_name}, |
||
West Midlands. |
West Midlands. |
||
WM4 5HD. |
WM4 5HD. |
||
END |
END |
||
</lang> |
|||
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: |
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: |
||
<lang ruby>pancake = <<"NO MORE INGREDIENTS" |
|||
<lang ruby> |
|||
pancake = <<"NO MORE INGREDIENTS" |
|||
egg |
egg |
||
milk |
milk |
||
flour |
flour |
||
NO MORE INGREDIENTS |
NO MORE INGREDIENTS |
||
</lang> |
|||
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string: |
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string: |
||
<lang ruby> |
<lang ruby> |
||
x = <<'FOO' |
|||
No |
No |
||
$interpolation |
$interpolation |
||
here |
here |
||
FOO |
FOO |
||
</lang> |
|||
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator: |
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator: |
||
<lang ruby> |
<lang ruby> |
||
output = <<`BAR` |
|||
ls /home |
ls /home |
||
BAR |
BAR |
||
</lang> |
|||
The here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression: |
The here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression: |
||
<lang ruby> |
<lang ruby> |
||
puts <<EOF + "lamb" |
|||
Mary had |
Mary had |
||
a little |
a little |
||
EOF |
EOF |
||
</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
<lang tcl> |
<lang tcl> |
||
set hereDocExample { |
|||
In Tcl, the {curly brace} notation is strictly a here-document style notation |
In Tcl, the {curly brace} notation is strictly a here-document style notation |
||
as it permits arbitrary content inside it *except* for an unbalanced brace. |
as it permits arbitrary content inside it *except* for an unbalanced brace. |
||
Line 350: | Line 448: | ||
backslash at the end of a line causes the end-of-line plus all whitespace at |
backslash at the end of a line causes the end-of-line plus all whitespace at |
||
the start of the next line to be compressed to a single space. |
the start of the next line to be compressed to a single space. |
||
} |
|||
}</lang> |
|||
</lang> |
|||
If substitution is desired within the document, it should either be written inside <tt>"</tt>double quotes<tt>"</tt> (instead of <tt>{</tt>braces<tt>}</tt>) ''or'' it should be passed through the <code>subst</code> command, which performs another round of substitutions. |
If substitution is desired within the document, it should either be written inside <tt>"</tt>double quotes<tt>"</tt> (instead of <tt>{</tt>braces<tt>}</tt>) ''or'' it should be passed through the <code>subst</code> command, which performs another round of substitutions. |
||
=={{header|TXR}}== |
=={{header|TXR}}== |
||
TXR was originally conceived out of the need to have "there documents": parse a document and |
TXR was originally conceived out of the need to have "there documents": parse a document and |
||
Line 363: | Line 464: | ||
which are interpreted by txr. |
which are interpreted by txr. |
||
<lang txr> |
<lang txr> |
||
#!/usr/bin/txr -f |
|||
@(maybe) |
@(maybe) |
||
@(bind USER "Unknown User") |
@(bind USER "Unknown User") |
||
Line 380: | Line 482: | ||
Test runs |
Test runs |
||
<pre> |
|||
<pre>$ ./quota.txr -DMB=20 |
|||
$ ./quota.txr -DMB=20 |
|||
Dear Unknown User |
Dear Unknown User |
||
Line 401: | Line 504: | ||
Unbound variables throw exceptions: |
Unbound variables throw exceptions: |
||
<pre>$ txr -c '@(output) |
|||
<pre> |
|||
$ txr -c '@(output) |
|||
@FOO |
@FOO |
||
@(end)' |
@(end)' |
||
Line 409: | Line 514: | ||
=={{header|UNIX Shell}}== |
=={{header|UNIX Shell}}== |
||
In the shell, here document act as input to the command, rather than providing a string definition. |
In the shell, here document act as input to the command, rather than providing a string definition. |
||
{{works with|Bourne Shell}} |
{{works with|Bourne Shell}} |
||
<lang bash> |
<lang bash> |
||
#!/bin/sh |
|||
cat << ANARBITRARYTOKEN |
cat << ANARBITRARYTOKEN |
||
The river was deep but I swam it, Janet. |
The river was deep but I swam it, Janet. |
||
Line 421: | Line 526: | ||
I've one thing to say and that's ... |
I've one thing to say and that's ... |
||
Dammit. Janet, I love you. |
Dammit. Janet, I love you. |
||
ANARBITRARYTOKEN |
ANARBITRARYTOKEN |
||
</lang> |
|||
<lang bash> |
<lang bash> |
||
cat << EOF |
|||
Here documents do parameter and command substitution: |
Here documents do parameter and command substitution: |
||
* Your HOME is $HOME |
* Your HOME is $HOME |
||
* 2 + 2 is `expr 2 + 2` |
* 2 + 2 is `expr 2 + 2` |
||
* Backslash quotes a literal \$, \` or \\ |
* Backslash quotes a literal \$, \` or \\ |
||
EOF |
EOF |
||
</lang> |
|||
<lang bash> |
<lang bash> |
||
if true; then |
|||
cat <<- EOF |
cat <<- EOF |
||
The <<- variant deletes any tabs from start of each line. |
The <<- variant deletes any tabs from start of each line. |
||
EOF |
EOF |
||
fi |
fi |
||
</lang> |
|||
<lang bash> |
<lang bash> |
||
cat << 'TOKEN' |
|||
If TOKEN has any quoted characters (like 'TOKEN', "TOKEN" or \TOKEN), |
If TOKEN has any quoted characters (like 'TOKEN', "TOKEN" or \TOKEN), |
||
then all $ ` \ in the here document are literal characters. |
then all $ ` \ in the here document are literal characters. |
||
$PATH \$PATH `shutdown now` |
$PATH \$PATH `shutdown now` |
||
TOKEN |
TOKEN |
||
</lang> |
|||
==={{header|C Shell}}=== |
==={{header|C Shell}}=== |
||
<lang csh> |
<lang csh> |
||
#!/bin/csh -f |
|||
cat << ANARBITRARYTOKEN |
cat << ANARBITRARYTOKEN |
||
* Your HOME is $HOME |
* Your HOME is $HOME |
||
Line 452: | Line 565: | ||
cat << 'ANARBITRARYTOKEN' |
cat << 'ANARBITRARYTOKEN' |
||
$PATH \$PATH `shutdown now` |
$PATH \$PATH `shutdown now` |
||
'ANARBITRARYTOKEN' |
'ANARBITRARYTOKEN' |
||
</lang> |
|||
=={{header|Ursala}}== |
=={{header|Ursala}}== |
||
<lang Ursala> |
|||
hd = |
|||
-[ |
-[ |
||
Line 523: | Line 637: | ||
{{omit from|Z80 Assembly}} |
{{omit from|Z80 Assembly}} |
||
{{omit from|ZX Spectrum Basic|Does not support here documents}} |
{{omit from|ZX Spectrum Basic|Does not support here documents}} |
||
=={{header|Microsoft NMAKE}}== |
|||
<lang nmake> |
|||
target0: dependent0 |
|||
command0 << |
|||
temporary inline file |
|||
... |
|||
<< |
|||
target1: dependent1 |
|||
command1 << |
|||
temporary, but preserved inline file |
|||
... |
|||
<<KEEP |
|||
target2: dependent2 |
|||
command2 <<filename2 |
|||
named, but discarded inline file |
|||
... |
|||
<<NOKEEP |
|||
target3: dependent3 |
|||
command3 <<filename3 |
|||
named inline file |
|||
... |
|||
<<KEEP |
|||
</lang> |
Revision as of 02:48, 1 December 2011
You are encouraged to solve this task according to the task description, using any language you may know.
A here document (or "heredoc") is a way of specifying a text block, preserving the line breaks, indentation and other whitespace within the text. Depending on the language being used a here document is constructed using a command followed by "<<" (or some other symbol) followed by a token string. The text block will then start on the next line, and will be followed by the chosen token at the beginning of the following line, which is used to mark the end of the textblock.
The task is to demonstrate the use of here documents within the language.
ALGOL 68
Algol 68 does not have a "heredoc" feature. It can be crudely achieved using an array of strings:
<lang algol68>
- !/usr/local/bin/a68g --script #
[]STRING help = ( "Usage: thingy [OPTIONS]", " -h Display this usage message", " -H hostname Hostname to connect to" );
printf(($gl$,help,$l$));
printf(($gl$, "The river was deep but I swam it, Janet.", "The future is ours so let's plan it, Janet.", "So please don't tell me to can it, Janet.", "I've one thing to say and that's ...", "Dammit. Janet, I love you." )) </lang>
Output:
Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to The river was deep but I swam it, Janet. The future is ours so let's plan it, Janet. So please don't tell me to can it, Janet. I've one thing to say and that's ... Dammit. Janet, I love you.
AutoHotkey
AutoHotkey uses "continuation sections" for literal text:
<lang AutoHotkey> MyVar = "This is the text inside MyVar" MyVariable = (
Note that whitespace is preserved As well as newlines. The LTrim option can be present to remove left whitespace. Variable references such as %MyVar% are expanded.
) MsgBox % MyVariable </lang>
C#
C# has a string literal call which is used for heredoc functionality
<lang C sharp> using System;
class Program {
static void Main(string[] args) { Console.Write(@"
multiline strings are easy to put together in C#");
}
} </lang>
CoffeeScript
CoffeeScript borrows the triple-quoted string syntax from Python. Note that these strings strip leading whitespace in CoffeeScript, to allow you to neatly align the heredoc string.
<lang coffeescript> myDoc =
Single-quoted heredocs allows no '#{foo}' interpolation. This behavior is similar to single-quoted strings.
doc2 = """
However, double-quoted heredocs *do* allow these. See it in action: Content: "#{myDoc}" """
console.log doc2 </lang>
The above would output the following:
However, double-quoted heredocs *do* allow these. See it in action: Content: "Single-quoted heredocs allows no '#{foo}' interpolation. This behavior is similar to single-quoted strings."
Note how the extra indentation in the third line of doc2 is preserved.
D
In D there are delimited strings: a 'q' followed by double quotes and an opening and closing delimiter of choice: <lang d> auto s = q"[a string that you "don't" have to escape]"; </lang>
If the delimiter is an identifier, the identifier must be immediately followed by a newline, and the matching delimiter is the same identifier starting at the beginning of the line:
<lang d> writefln(q"EOS This is a multi-line heredoc string EOS" ); </lang>
a string you " " don't have to escape This is a multi-line heredoc string
Go
Go does not have here documents. Multiline string literals serve this purpose.
<lang go> var m = ` leading spaces
and blank lines` </lang>
J
<lang j> here=:0 :0
0 :0 will be replaced by the text on the following lines. This is three tokens: two instances of the number 0 and one instance of the explicit definition token ':'. Any indentation in the here document will be retained in the result. There must be a space to the left of : or it will combine with the 0 on its left to form the token 0: which is something completely different.
The here document is terminated by a line which contains only a single right parenthesis ')' and optional white space. In J's documentation the family of entities which include here documents (and verb definitions and so on) are called 'scripts'.
When several scripts are referenced on the same line, they are used sequentially in an order determined by their appearance on the line. The leftmost 'script' reference gets the last script and the rightmost reference gets the first script. But this is a rare usage.
Typically, such values are assigned a name so that they can be used later. However, they may also be discarded and/or ignored, in which case they are logically equivalent to multi-line comments.
)
and_here=:noun define
'noun define' is an alternative and perhaps more "user friendly" way of declaring a here document. It achieves the same thing as 0 :0 and in fact 'noun' has the value 0 and 'define' has the value :0 And, of course, there must be a space between the word 'noun' and the word 'define'.
Other useful alternatives include verb (which has the value 3) and dyad (which has the value 4), and adverb (which has the value 1). In other words 'verb define' (if unquoted) would be replaced by a verb whose definition is provided in the following 'script'. However, all of these names are normal variables which can be declared to have different values by the developer. And, of course, note that this mechanism is significantly more verbose than using the underlying 0 :0 mechanism directly.
) </lang>
NMAKE.EXE
<lang nmake.exe> target0: dependent0
command0 <<
temporary, discarded inline file ... <<
target1: dependent1
command1 <<
temporary, but preserved inline file ... <<KEEP
target2: dependent2
command2 <<filename2
named, but discarded inline file ... <<NOKEEP
target3: dependent3
command3 <<filename3
named and preserved inline file ... <<KEEP </lang>
Perl
In Perl, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised. Interpolation is allowed, like a double-quoted string:
<lang perl> $address = <<END; 1, High Street, $town_name, West Midlands. WM4 5HD. END </lang>
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit: <lang perl> $pancake = <<"NO MORE INGREDIENTS"; egg milk flour NO MORE INGREDIENTS </lang>
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string:
<lang perl> $x = <<'FOO'; No $interpolation here FOO </lang>
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator:
<lang perl> $output = <<`BAR`; ls /home BAR </lang>
Note that in the above examples, that a semicolon was left after the here document's token string. This is because (unlike PHP) the here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression:
<lang perl> print(<<EOF . "lamb\n"); Mary had
a little
EOF </lang>
Although, technically speaking, it is also possible to break a statement into two parts, with the here document in the middle (i.e. continue the statement on the line after the terminating token). However, please don't do this.
<lang perl> print(<<EOF Mary had
a little
EOF
. "lamb\n");
</lang>
Perl 6
Heredocs in Perl 6 use the :to
modifier to a quoting operator, such as q
or qq
. Multiple here docs may be stacked on top of each other.
<lang perl6> my $contrived_example = 'Dylan'; sub freewheelin() {
print q :to 'QUOTE', '-- ', qq :to 'AUTHOR'; I'll let you be in my dream, if I can be in yours. QUOTE Bob $contrived_example AUTHOR
}
freewheelin; </lang>
Output:
I'll let you be in my dream, if I can be in yours. -- Bob Dylan
PHP
In PHP, the here document symbol is 3 less-than signs, not two: <<<
There must not be a space between the "<<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, except for a possible semicolon. Interpolation is allowed, like a double-quoted string:
<lang php> $address = <<<END 1, High Street, $town_name, West Midlands. WM4 5HD. END; </lang>
In PHP 5.3+, it is possible to make a here-document that does not interpolate (PHP calls this a "nowdoc"), by surrounding the token with single-quotes (like in Perl):
<lang php> $x = <<<'FOO' No $interpolation here FOO; </lang>
PicoLisp
We can use the 'here' function:
<lang PicoLisp> (out "file.txt" # Write to "file.txt"
(prinl "### This is before the text ###") (here "TEXT-END") (prinl "### This is after the text ###") )
"There must be some way out of here", said the joker to the thief "There's too much confusion, I can't get no relief" TEXT-END
(in "file.txt" (echo)) # Show "file.txt" </lang>
Output:
### This is before the text ### "There must be some way out of here", said the joker to the thief "There's too much confusion, I can't get no relief" ### This is after the text ###
Python
Python does not have here-docs. It does however have triple-quoted strings which can be used similarly.
<lang python> print("""\ Usage: thingy [OPTIONS]
-h Display this usage message -H hostname Hostname to connect to
""") </lang>
Retro
Retro does not have a builtin here document. It does support multiline strings:
<lang Retro> "This is
a multi-line string with indention
and such" </lang>
If you need an actual heredoc function, the following should suffice:
<lang Retro> {{
: getDelimiter ( "-$ ) getToken keepString cr ; : prepare ( -$ ) remapping off "" tempString ; : readLine ( "-$ ) 10 accept tib ; : append? ( $$-$$f ) [ over ] dip compare [ 0 ] [ tib ^strings'append 10 ^strings'appendChar -1 ] if ;
---reveal---
: heredoc ( "-$ ) heap [ remapping [ getDelimiter prepare [ readLine append? ] while nip ] preserve ] preserve ;
}}
heredoc [END] 1 2 3
4 5 6 7 8 9
[END] </lang>
Ruby
In Ruby, there must not be a space between the "<<" and the token string. The ending token must always be the entire end line (i.e. no surrounding spaces) for it to be recognised, unless you use "<<-" instead of "<<", in which case indentation before the ending token is allowed. Interpolation is allowed, like a double-quoted string:
<lang ruby> address = <<END 1, High Street,
- {town_name},
West Midlands. WM4 5HD. END </lang>
If the token string contains spaces, the token after the "<<" must be quoted; otherwise the double-quotes is implicit:
<lang ruby> pancake = <<"NO MORE INGREDIENTS" egg milk flour NO MORE INGREDIENTS </lang>
It is possible to make a here-document that behaves differently than a double-quoted string, by applying a different kind of quoting to the token. For example, if you use single quotes, then the here document will not support interpolation, like a normal single-quoted string:
<lang ruby> x = <<'FOO' No $interpolation here FOO </lang>
Alternately, you can use backticks to cause the here document to be executed and the result returned, just like a normal backtick operator:
<lang ruby> output = <<`BAR` ls /home BAR </lang>
The here document does not start immediately at the "<<END" token -- it starts on the next line. The "<<END" is actually an expression, whose value will be substituted by the contents of the here document. The "<<END" must still live inside a valid statement on the line that it's used. To further illustrate this fact, we can use the "<<END" inside a complex, nested expression:
<lang ruby> puts <<EOF + "lamb" Mary had
a little
EOF </lang>
Tcl
<lang tcl> set hereDocExample { In Tcl, the {curly brace} notation is strictly a here-document style notation as it permits arbitrary content inside it *except* for an unbalanced brace. That is typically not a problem as seen in reality, as almost all content that might be placed in a here-doc is either brace-free or balanced. The content of the braces is not interpreted at all; no substitutions are performed on it.
The sole exception is that there is limited processing of backslashes; a single backslash at the end of a line causes the end-of-line plus all whitespace at the start of the next line to be compressed to a single space. } </lang>
If substitution is desired within the document, it should either be written inside "double quotes" (instead of {braces}) or it should be passed through the subst
command, which performs another round of substitutions.
TXR
TXR was originally conceived out of the need to have "there documents": parse a document and extract variables, but in a style similar to generation of here documents. Here doc output was added later.
We use @(maybe)/@(or)/@(end) to set up some default values for variables which are overridden from the command line. Unification fails for an overridden variable, which is why we have to separate out the bind directives into the branches of a maybe.
By passing the script to txr using -f we can pass additional command arguments to the resulting script which are interpreted by txr.
<lang txr>
- !/usr/bin/txr -f
@(maybe) @(bind USER "Unknown User") @(or) @(bind MB "???") @(end) @(output) Dear @USER
Your are over your disk quota by @MB megabytes.
The Computer @(end) </lang>
Test runs
$ ./quota.txr -DMB=20 Dear Unknown User Your are over your disk quota by 20 megabytes. The Computer $ ./quota.txr -DUSER=Bob Dear Bob Your are over your disk quota by ??? megabytes. The Computer $ ./quota.txr -DUSER=Bob -DMB=15 Dear Bob Your are over your disk quota by 15 megabytes. The Computer
Unbound variables throw exceptions:
$ txr -c '@(output) @FOO @(end)' txr: unhandled exception of type query_error: txr: (cmdline:2) bad substitution: FOO
UNIX Shell
In the shell, here document act as input to the command, rather than providing a string definition.
<lang bash>
- !/bin/sh
cat << ANARBITRARYTOKEN The river was deep but I swam it, Janet. The future is ours so let's plan it, Janet. So please don't tell me to can it, Janet. I've one thing to say and that's ... Dammit. Janet, I love you. ANARBITRARYTOKEN </lang>
<lang bash> cat << EOF Here documents do parameter and command substitution:
* Your HOME is $HOME * 2 + 2 is `expr 2 + 2` * Backslash quotes a literal \$, \` or \\
EOF </lang>
<lang bash> if true; then cat <<- EOF The <<- variant deletes any tabs from start of each line. EOF fi </lang>
<lang bash> cat << 'TOKEN' If TOKEN has any quoted characters (like 'TOKEN', "TOKEN" or \TOKEN), then all $ ` \ in the here document are literal characters.
$PATH \$PATH `shutdown now` TOKEN </lang>
C Shell
<lang csh>
- !/bin/csh -f
cat << ANARBITRARYTOKEN
* Your HOME is $HOME * 2 + 2 is `@ n = 2 + 2; echo \$n`
ANARBITRARYTOKEN
cat << 'ANARBITRARYTOKEN' $PATH \$PATH `shutdown now` 'ANARBITRARYTOKEN' </lang>
Ursala
<lang Ursala> hd =
-[ The text enclosed within the so called dash-brackets shown above and below will be interpreted as a list of character strings. It can contain anything except uninterpreted dash-brackets, and can be used in any declaration or expression. The dash-brackets don't have to be on a line by themselves. ]-
example =
-[Some additional facilities allow here-documents to be nested and combined. Writing something like -[ hd ]- within a nested pair of dash-brackets will cause the text declared above (having the identifer hd) to be inserted at that point. The enclosed item can be any expression that evaluates to a list of character strings. We could therefore "escape" a literal dash-bracket within a here-document by writing -[ <'-['> ]-. Dash-brackets can be nested to any depth, alternating between literal text and compiled code on each level.]-
template "x" =
-[A further use of this notation involves defining a text-valued function. The output of this function will be this text, with the argument inserted here -["x"]- and again here -["x"]-. The argument type should be a list of character strings.]-
formletter ("x","y") =
-[Other calling conventions are possible. The left argument comes out here -["x"]- and the right one here -["y"]-.]-
designpattern =
-[A point-free style of function declaration is also supported. The argument comes out here -[. ~& ]-, after being fed through the function appearing within the nested dash-brackets (in this case the identity function). This usage is indicated by a period after the left inner dash-bracket. Nesting is also allowed in point free dash-bracket function specifications.]-
abstractionastronaut =
-[Higher order functions to any level are specified by piling on the periods like this -[.. ~&]-. This one is a second order function that needs to be applied to another function in order to get a first order function such as the previous three examples.]-
</lang>
- Programming Tasks
- Solutions by Programming Task
- ALGOL 68
- AutoHotkey
- C sharp
- CoffeeScript
- D
- Go
- J
- NMAKE.EXE
- Perl
- Perl 6
- PHP
- PicoLisp
- Python
- Retro
- Ruby
- Tcl
- TXR
- UNIX Shell
- C Shell
- Ursala
- 8086 Assembly/Omit
- 80386 Assembly/Omit
- BASIC/Omit
- C/Omit
- GUISS/Omit
- Icon/Omit
- Unicon/Omit
- Java/Omit
- JavaScript/Omit
- Locomotive Basic/Omit
- Lotus 123 Macro Scripting/Omit
- Openscad/Omit
- Z80 Assembly/Omit
- ZX Spectrum Basic/Omit