Here document notations [duplicate] - shell

This question already has answers here:
here-document gives 'unexpected end of file' error
(10 answers)
Closed 2 years ago.
I cannot find much explanation regarding a notation in here documents. In my shell script, I am plotting a file with gnuplot.
This code works:
gnuplot <<- EOF
set xlabel "square dimension (inches)"
set ylabel "mean survival time (seconds)"
set term png
set output "${plot_file}.png"
plot "beetle.dat" using 1:2
EOF
However, if I do not include the dash in <<- and just use <<, this code does not work and I get the following error:
./myscript: line 118: warning: here-document at line 104 delimited by end-of-file (wanted `EOF')
./myscript: line 119: syntax error: unexpected end of file
This question might have been asked before, however due to special characters not being recognized, I cannot search for it.

When you say "this code", is it that code - or is it indented ?
Heredocs by default look for a line containing ONLY the delimiter, so no leading tabs or spaces. What the "-" does is remove leading tabs, so you can indent the heredoc (both content and delimiter) prettily in line with the rest of your code.
So if your delimiter is actually indented in the code, it will only be found with the "-"
See 3.6.6 in https://www.gnu.org/software/bash/manual/html_node/Redirections.html

Related

Cannot read lines from a file using bash read command [duplicate]

This question already has answers here:
Shell script read missing last line
(7 answers)
Closed 2 years ago.
Created a text file as hello_world.rtf with following two lines only:
Hello
World
and trying to read above file using below bash script from terminal:
while test= read -r line; do
> echo "The text read from file is: $line"
> done < hello_world.rtf
and it returns the following:
The text read from file is: {\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf500
The text read from file is: {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
The text read from file is: {\colortbl;\red255\green255\blue255;}
The text read from file is: {\*\expandedcolortbl;;}
The text read from file is: \paperw12240\paperh15840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
The text read from file is: \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
The text read from file is:
The text read from file is: \f0\fs24 \cf0 Hello\
Any suggestion what is wrong here and how can I get the clean result?
RTF means Rich Text Format. It is a language for text formatting, developed and used mostly by Microsoft and deprecated for a while.
The text inside the file looks as you can see in the output of your code. It contains the words "Hello" and "World" but also formatting instructions.
Save the file as plain text, not RTF and it will contain only the text you typed in it.
test= in front of read does not have any effect in this context. You can remove it.
Make sure the last line of the file ends with a new-line character. read returns an non-zero exit status (and this means false) when it reaches the end of file and your code exits the while loop and does not display the last value read by read. If the file ends with a new-line character, the last line (that is read but not listed by the code) is empty, therefore nothing is lost.
It is a recommended practice for text files to always end with a newline character.
Alternatively you can print the value of line again after the loop. It contains the last line of the file (from the last end-of-line character until the end of file).

If bash variable value contains space, the script chokes [duplicate]

This question already has answers here:
Reading complete line in 'for' loop with spaces, tabs with multiple input files
(1 answer)
Reading key/value parameters from a file into a shell script
(1 answer)
Closed 4 years ago.
I have a bash script that parses an xml file (name: myFile.xml) that looks like this:
<?xml version="1.0" encoding="utf-8"?>
<params>
<username>jDoe</username>
<password>123abc</password>
<fullname>John Doe</fullname>
<email>johndoe#example.com</email>
<phone>1234567890</phone>
<country>Italy</country>
</params>
In that bash script, I parse each value of the xml file into a variable for further use. So far the bash script looks like that:
for i in $(xmlstarlet select --template --match "//params/*" --value-of "concat(name(),'=\"',text(),'\"')" -n myFile.xml)
do
eval $i
done
#debugging:
echo $username
echo $fullname
echo $password
When I run this script
./myScript.sh
I get the following output:
./myScript.sh: eval: line 34: unexpected EOF while looking for matching `"'
./myScript.sh: eval: line 35: syntax error: unexpected end of file
./myScript.sh: eval: line 34: unexpected EOF while looking for matching `"'
./myScript.sh: eval: line 35: syntax error: unexpected end of file
jDoe
123abc
Apparently, because the tag <fullname> has a value of 2 words separated by space the script chokes. If I replace it's value "John Doe" with another (with no space) like: "JohnDoe" or "John_Doe" the script works fine!
Any suggestions as to how I can pass to a bash variable a value that contains space?
Of course, I would like to maintain the loop because
1. the actual script has too many parameters
and 2. the parameters are not always the same (they vary from one xml file to another)...
(and to cut the long story short, this is what I would like to achieve: fullname="John Doe")

how to hide warning in bash script [duplicate]

This question already has answers here:
Suppress warning output in bash
(3 answers)
here-document gives 'unexpected end of file' error
(10 answers)
Closed 6 years ago.
I have a bash script I've been using for ages. It has a few lines it just start/stop some jobs in database. It is very simple and it never fails. Last year, it facts in December so a few days ago :) I migrated whole data to a new machine. And then my problem starts.
Now script works as it worked before but now it returns warning. Below output:
[oracle#SVMSLUATTIADB1 ~]$ ./batch.sh stop
./batch.sh: line 87: warning: here-document at line 85 delimited by end-of-file (wanted `!')
./batch.sh: line 87: warning: here-document at line 85 delimited by end-of-file (wanted `!')
Batch_Executer_1 [NOT OK]
Batch_Executer_2 [NOT OK]
[oracle#SVMSLUATTIADB1 ~]$
The piece of code mentioned in warning is:
batch_stop()
{
for BATCH in $BATCHES
do
SQLRES=`sqlplus -S "/ as sysdba" << !
exec dbms_scheduler.disable('"AIT"."${BATCH}"', TRUE);
` << line 87
done
}
So the question is how to avoid/hide this warnings. It is not critical, script works as it worked but the view of warning disturbs. I see that before I had bash version 3.2.25 but now it is bash 4.1.2.
I tried to modified my code and redirected output :
{SQLRES=`sqlplus -S "/ as sysdba" << !
exec dbms_scheduler.disable('"AIT"."${BATCH}"', TRUE);
` } 2>/dev/null
but it didn't help :(
The warning is caused by invalid here document syntax. Namely, the second limit word ("!") is missing.
Also, don't use back quotes for command substitution. Use the $(...) syntax instead, as it is more readable, and it can be nested.
The fixed version:
SQLRES=$(sqlplus -S "/ as sysdba" << !
exec dbms_scheduler.disable('"AIT"."${BATCH}"', TRUE);
!
)
Note, the here document ends on a line containing only the limit word (the exclamation mark, in particular). So it is not allowed to indent the second limit word, for example.

Bash script sourcing config file but can't use vars in arithmetic

This is killing me. I have a config file, "myconfig.cfg", with the following content:
SOME_VAR=2
echo "I LOVE THIS"
Then I have a script that I'm trying to run, that sources the config file in order to use the settings in there as variables. I can print them out fine, but when I try to put one into a numeric variable for use in something like a "seq " command, I get this weird "invalid arithmetic operator" error.
Here's the script:
#!/bin/bash
source ./myconfig.cfg
echo "SOME_VAR=${SOME_VAR}"
let someVarNum=${SOME_VAR}
echo "someVarNum=${someVarNum}"
And here's the output:
I LOVE THIS
SOME_VAR=2
")syntax error: invalid arithmetic operator (error token is "
someVarNum=
I've tried countless things that theoretically shouldn't make a difference, and, surprise, they don't. I simply can't figure it out. If I simply take the line "SOME_VAR=2" and put it directly into the script, everything's fine. I'm guessing I'll have to read in the config file line by line, split the strings by "=", and find+create the variables I want to use manually.
The error is precisely as indicated in a comment by #TomFenech. The first line (and possibly all the lines) in myconfig.cfg is terminated with a Windows CR-LF line ending. Bash considers CR to be an ordinary character (not whitespace), so it will set SOME_VAR to the two character string 2CR. (CR is the character with hex code 0x0D. You could see that if you display the file with a hex-dumper: hd myconfig.cfg.)
The let command performs arithmetic on numbers. It also considers the CR to be an ordinary character, but it is neither a digit nor an operator so it complains. Unfortunately, it does not make any attempt to sanitize the display of the character in the error message, so the carriage return is displayed between the two " symbols. Consequently, the end of the error message overwrites the beginning.
Don't create Unix files with a Windows text editor. Or use a utility like dos2unix to fix them once you copy them to the Unix machine.

Unexpected EOF?

I have been trying to create a graph in GNUPLOT using Bash. As I understand it, my following code should input the following lines into the gnuplot command until it reaches an EOF. I then send the "set" lines and "plot" line to gnuplot and follow it up with an EOF, which should end the input into the gnuplot command.
for FILE in ./tempFolder*.done; do
gnuplot <<EOF
set datafile separator ","
set xlabel "Hour"
set ylabel "Temperature"
set term png
set output "${FILE}.png"
plot "${FILE}" using 1:3 with errorbars title "Temperature/Time"
EOF
done
However, I get the following error message: "Syntax error: end of file unexpected (expecting "done")"
When I type try this in Bash outside of the script, it seems to work properly. Anyone have any pointers as to what I'm doing wrong?
You cannot indent the closing EOF; it has to be at the beginning of the line.
If you use <<-EOF instead of <<EOF, the shell will strip any leading tabs from each line of the here document, including the closing EOF.

Resources