I'm currently learning Unix bash, through the terminal in Ubuntu 16. I was writing a simple script, so I can practice writing code for Unix. Here is a sample of the code:
report_uptime(){
cat << _EOF_
<H2>System Uptime</H2>
<PRE>$(uptime)</PRE>
_EOF_
return
}
This code doesn't work and the reason is because after cat I'm supposed to use <<-
instead of <<
. Sometime <<
works. So when am I supposed to use <<
and when am I supposed to use<<-
?
This works:
report_uptime(){
cat <<- _EOF_
<H2>System Uptime</H2>
<PRE>$(uptime)</PRE>
_EOF_
return
}
This isn't cat syntax per se; it's one of the redirection operators supported by your shell:
https://www.gnu.org/software/bash/manual/bashref.html#Here-Documents
3.6.6 Here Documents
This type of redirection instructs the shell to read input from the current source until a line containing only word (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input for a command.
The format of here-documents is:
<<[-]word here-document delimiter
No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence
\newline
is ignored, and ‘\’ must be used to quote the characters ‘\’, ‘$’, and ‘`’.If the redirection operator is ‘<<-’, then all leading tab characters are stripped from input lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.
This is not strictly speaking about the syntax of the cat
utility, but of the syntax of the shell itself, i.e. of bash
.
The construct that you're using is called a "here-document". A here-document feeds its contents into the standard input of whatever command you put before <<
.
The syntax is this:
command <<word
...
contents
...
END_TAG
The word
here is either exactly the same as the END_TAG
, or it may be 'END_TAG'
, -END_TAG
, or -'END_TAG'
.
END_TAG
: Without single quotes, the contents of the here-document will undergo substitution. This means that any variable, or simply put, "anything that contains a $
" will be replaced with its value.
$ tr 'a-z' 'A-Z' <<TR_END
> This is my $HOME
> TR_END
THIS IS MY /USERS/KK
(The >
, a greater-than sign and a space, is what's called the secondary prompt. I get that because I'm typing this directly into the shell, and it needs more lines of input before it can execute the whole command. It is not typed by me.)
'END_TAG'
: With single quotes, the contents of the here-document will not undergo substitution. This means, for example, that if you write $HOME
in the here-document, it will be fed into the command just like that, not like /home/myname
(or whatever your home directory may be).
$ tr 'a-z' 'A-Z' <<'TR_END'
> This is my $HOME
> TR_END
THIS IS MY $HOME
With a leading dash (-
), the shell will strip off all tabs (but not spaces) at the start of each line of the here-document, including the line with the END_TAG
at the end.
$ tr 'a-z' 'A-Z' <<-TR_END
> This line has a tab.
> This one does not.
> TR_END
THIS LINE HAS A TAB.
THIS ONE DOES NOT.
Without a leading dash, the shell will not strip off tabs. The END_TAG
needs to be the first (and only) thing on the line ending the here-document.
$ tr 'a-z' 'A-Z' <<TR_END
> This line has a tab.
> This one does not.
> TR_END
THIS LINE HAS A TAB.
THIS ONE DOES NOT.
The bash
shell also has something called "here-strings". It works in a similar fashion, but you're only feeding a single line into the command:
command <<<word
For example:
$ tr 'a-z' 'A-Z' <<<"hello world!"
HELLO WORLD!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With