ambiguous redirect - file gets created - shell

I get an ambiguous redirect message even though the output file gets created.
my sh script
#!/bin/bash
# you can use read or VAR="$1" to setup these variables
SERVER_IP=
SERVER_PORT=
LANGUAGE_URL=
PROJECT_NAME=
while read f1
do
OUTPUTFIL=$f1
{
echo "<?xml version=\"1.0\" encoding=\"Shift-JIS\"?>"
echo "<flash_cfg>"
echo "<server ip=\"${SERVER_IP}\" port=\"${SERVER_PORT}\"/>"
echo "<language_url>${LANGUAGE_URL}</language_url>"
echo "<project_name>${PROJECT_NAME}</project_name>"
echo "</flash_cfg>"
} > ${OUTPUTFIL}
done < file
content of "file
out.xml
while running
:~/Documents$ bash shell.sh
shell.sh: line 22: ${OUTPUTFIL}: ambiguous redirect
The file out.xml is created however

No contradiction there, you have a loop.
So first you read a valid filename (out.xml), and create a file, then you're reading an invalid one, which creates the error message.
Example (you have an empty line in the input):
f=""
echo "Q" > ${f}
-bash: ${f}: ambiguous redirect

I'd use cat to simplify the code--see if this works any better:
while read f1
do
cat <<EOF >"$f1"
<?xml version="1.0" encoding="Shift-JIS"?>
<flash_cfg>
<server ip="${SERVER_IP}" port="${SERVER_PORT}"/>
<language_url>${LANGUAGE_URL}</language_url>
<project_name>${PROJECT_NAME}</project_name>
</flash_cfg>
EOF
done < file
That's known as a "here document" and lets you avoid all those echo's and quoting.

Related

How can I disable * expansion in a script?

I have a strange problem - possibly I'm just going blind. I have this short script, which replaces the string #qry# in the here-document with a select statement in a file and then pipes it to mysql:
#!/bin/bash
if [[ "$1" == "-h" ]]
then
echo "sqljob [sqlfile] [procnm] [host] [database] [config file]"
echo " sqlfile: text file containing an SQL statement"
echo " procnm: name that will given to the new, stored procedure"
echo " host: hostname of IP address of the database server"
echo " database: the procedure will be created here"
echo " config file: default configuration file with username and password"
exit
fi
infile=$1
procnm=$2
hn=$3
pn=$4
db=$5
mycfg=$6
{
set -o noglob
sed -e "s/#qry#/$(echo $(cat $infile))/g" <<!
drop procedure if exists $procnm;
delete from jobs where jobname="$procnm";
insert into jobs
set
notes="SQL job $procnm",
jobname="$procnm",
parm_tmpl='int';
delimiter //
create procedure $procnm(vqid int)
begin
call joblogmsg(vqid,0,"$procnm","","Executing #qry#");
drop table if exists ${procnm}_res;
create table ${procnm}_res as
#qry#
end//
delimiter ;
!
} | mysql --defaults-file=$mycfg -h $hn -P $pn $db
However, when the select contains *, it expands to whatever is in the directory even though I use noglob. However, it works from the command line:
$ set -o noglob
$ ls *
What am I doing wrong?
Edit
Block Comments in a Shell Script has been suggested as a duplicate, but as you will notice, I need to expand ${procnm} in the here-doc; I just need to avoid the same happening to select *.
I suspect it is because the construct echo (cat). The echo command gets the * from the cat command and the shell in which it runs expands it. In that shell set noglob is not active.
Try leaving the echo away: /$(cat $infile)/, in the end that is the data you need; then there is no extra glob expansion by a shell.

Echo printing variables in a completely wrong order

I am trying to create a string with a query that will be save / send to another location, this string contains different variables.
The issue that I am having is that the echo of the variables are completely upside down and mix.
See code below:
tokenID=$(docker exec -ti $dockerContainerID /bin/sh -c "cat /tempdir/tokenfile.txt")
serverName="asdasd"
attQuery="$tokenID $serverName"
agentRegQuery="$./opt/mule/bin/amc_setup -H $attQuery"
echo TOKEN ID $tokenID
echo SERVER NAME $serverName
echo $attQuery
echo $agentRegQuery
Find below the output I am receiving:
TOKEN ID 29a6966f-fa0e-4f08-87eb-418722872d80---46407
SERVER NAME asdasd
asdasdf-fa0e-4f08-87eb-418722872d80---46407
asdasdmule/bin/amc_setup -H 29a6966f-fa0e-4f08-87eb-418722872d80---46407
There's a carriage return character at the end of the tokenID variable, probably because /tempdir/tokenfile.txt is in DOS/Windows format (lines end with carriage return+linefeed), not unix (lines end with just linefeed). When you print tokenID by itself, it looks ok, but if you print something else after that on the same line, it winds up overwriting the first part of the line. So when you print $attQuery, it prints this:
29a6966f-fa0e-4f08-87eb-418722872d80---46407[carriage return]
asdasd
...but with the second line printed on top of the first, so it comes out as:
asdasdf-fa0e-4f08-87eb-418722872d80---46407
The solution is to either convert the file to unix format (dos2unix will do this if you have it), or remove the carriage return in your script. You can do it like this:
tokenID=$(docker exec -ti $dockerContainerID /bin/sh -c "cat /tempdir/tokenfile.txt" | tr -d '\r')
I think everything works as it should
echo TOKEN ID $tokenID -> TOKEN ID 29a6966f-fa0e-4f08-87eb-418722872d80---46407
echo SERVER NAME $serverName -> SERVER NAME asdasd
echo $attQuery -> asdasdf-fa0e-4f08-87eb-418722872d80---46407
echo $agentRegQuery -> asdasdmule/bin/amc_setup -H 29a6966f-fa0e-4f08-87eb-418722872d80---46407
Why do you think something is wron here?
Best regards, Georg

bash for script and input parameter

Can anyone help me to modify my script. Because it does not work. Here are three scripts.
1) pb.sh, use delphicpp_release software to read the 1brs.ab.sh and will give the output as 1brs.ab.out
2) 1brs.ab.sh, use for input parameter where a.sh(another script for protein structure), chramm.siz, charmm.crg are file for atom size and charge etc. rest of the parameters for run the delphicpp_release software.
3) a.sh, use for read several protein structures, which will be in the same directory.
my script_1 = pb.sh:
./delphicpp_release 1brs.ab.sh >1brs.ab.out
echo PB-Energy-AB = $(grep -oP '(?<=Energy> Corrected:).*' 1brs.ab.out) >>PB-energy.dat
cat PB-energy.dat
script_2 = 1brs.ab.sh:
in(pdb,file="a.sh")
in(siz,file="charmm.siz")
in(crg,file="charmm.crg")
perfil=70
scale=2.0
indi=4
exdi=80.0
prbrad=1.4
salt=0.15
bndcon=2
maxc=0.0001
linit=800
energy(s)
script_3 = a.sh:
for i in $(seq 90000 20 90040); do
$i.pdb
done
As we don't know what software is, something like
for ((i=90000;i<=100000;i+=20)); do
./software << " DATA_END" > 1brs.$i.a.out
scale=2.0
in(pdb,file="../$i.ab.pdb")
in(siz,file="charmm.siz")
in(crg,file="charmm.crg")
indi=z
exdi=x
prbrad=y
DATA_END
echo Energy-A = $(grep -oP '(?<=Energy>:).*' 1brs.$i.a.out) >>PB-energy.dat
done
A more POSIX shell compliant version
i=90000
while ((i<=100000)); do
...
((i+=20));
done
EDIT: Without heredoc
{
echo 'scale=2.0'
echo 'in(pdb,file="../'"$i"'.ab.pdb")'
echo 'in(siz,file="charmm.siz")'
echo 'in(crg,file="charmm.crg")'
echo 'indi=z'
echo 'exdi=x'
echo 'prbrad=y'
} > $i.ab.sh
./software <$i.ab.sh >$i.ab.out
but as question was changed I'm not sure to understand it.

What & How does this line of code work: {message:0:1} {message:23:17}

Would love for someone to help educate me on this line of code.
using diff command to compare two files which somehow allows for other commands such as message:0:1 and message:23:17 to access it's results.
How does this work?
message=$(diff previousscan.txt scan.txt | grep 192)
#get first char which indicates if the host came up or went away
iostring="${message:0:1}"
#get first ip-number from the list
computer="${message:23:17}"
#show ip-number in notify if host came up
if [ "$iostring" = \> ]; then
notify-send "$computer online"
fi
#show ip-number in notify if host went away
if [ "$iostring" = \< ]; then
notify-send "$computer offline"
fi
$message is not a command; it is a variable which holds the output of the diff command. The later lines reference substrings; ${message:0:1} is the first character (1 character starting at offset 0) of whatever is stored in $message.
A simple example to show the substring mechanism:
$ message="abcdefghijklmnop"
$ echo ${message:0:1}
a
$ echo ${message:7:3}
hij
The construction foo=$(bar) runs the command bar in a subshell, and places the output you would normally see in your terminal if you simply ran the command bar in the variable $foo.

how to write an empty line in file from a variable?

In Windows Command Line I normally write empty line in a file with
echo; >> file
However, what I have now is a variable
$param1%
If I want echo to write it in the file I have to do
echo %param1% >> file
HERE IS WHERE THE PROBLEM START :
If I'd like an empty like I'd make
set param1=;
However since the ; is not in contact with the echo word the command is
echo ; >> file
which write the ; in the file...
I need the variable to sometime contains text, and sometime nothing. How can I do it?
if "%param1%"=="" echo;>>file else echo %param1%>>file
If a param1 variable does not exist (the same as set "param1="), then %param1% results to:
In a .bat script: %param1% results to an empty string (a string of zero length);
In a CLI window: %param1% results to the %param1% string.
In a .bat script use (note no spaces surrounding %param1%)
>> file (echo;%param1%)
In a CLI window use
>>file (if not defined param1 (echo;) else echo;%param1%)
Note proper using of parentheses in if-else! For instance, check interesting result of next command:
if ""=="" echo;"THEN branch">>file else echo;"ELSE branch">>file
Output:
==>if ""=="" echo;"THEN branch">>file else echo;"ELSE branch">>file
==>type file
"THEN branch" else echo;"ELSE branch"

Resources