Single echo statement displaying values in 2 lines - bash

The echo statement below is displaying values in 2 line instead of single line (Redirect File).
echo ">>"`date`": Value1: " $VAL1 "Value2:" $VAL2>>$RES_FILE
Actual Result:
>>Tue Dec 1 10:20:24 IST 2015: Value1:1
Value2:2
Expected Result:
>>Tue Dec 1 10:20:24 IST 2015: Value1:1 Value2:2
Tell me whats wrong with the statement.

There's no problem with your usage of echo. From your output, it looks like there's a newline in VAL1.
You try removing it:
VAL1="${VAL1//$'\n'}"

Related

Strange Behavior in Bash For Loop

Given the following code, BASH's output is unexpected for me and I'm looking for possible solutions (I've tried changing the way I'm quoting but that doesn't seem to affect anything to produce the desired result):
Testing File:
#!/bin/bash
. FindMissingSettings.function
Settings[0]="FirstSetting"
Settings[1]="SecondSetting"
Settings[2]="ThirdSetting"
ThisFile="ThisFile"
find_missing_settings "${Settings[#]}" "$ThisFile"
The included FindMissingSettings.function:
#!/bin/bash
find_missing_settings () {
Settings=("$#")
File=$2
for Setting in "${Settings[#]}"; do
echo "$Setting"
echo "1"
done
echo "$File"
echo "2"
}
I expected the output from this script and the included function to be:
FirstSetting
1
SecondSetting
1
ThirdSetting
1
ThisFile
2
However this was the result I received:
FirstSetting
1
SecondSetting
1
ThirdSetting
1
ThisFile
1
SecondSetting
2
Why is this and what can I do to provide the desired result? Thank you!
In your find_missing_settings function, in your variable Setting, you have all the given inputs (FirstSetting, Second Setting, ThirdSetting, ThisFile). That's why it print it all with during the loop.
Then it print the 2nd setting in the list, so SecondSetting
To fix this, you can put ThisFile as first parameter of the function:
find_missing_settings "$ThisFile" "${Settings[#]}"
And change in the find_missing_settings function how you get the inputs:
Settings=("${#:2}")
File=$1
The :2 ask to get the inputs starting from the 2nd one only, and you put the first one (ThisFile) in the variable File

Syntax error at line 1 : `(' is not expected

As I'm new to Unix, can someone help why I get this error?
Error: 0403-057 Syntax error at line 1 : `(' is not expected
Unix server used: AIX servname 1 6 00F635064C00
Script used (to send email alert if day before yesterday source files didn't arrive):
#!/usr/bin/ksh
count=$(sqlplus $PROD_DB #select count(*) from file_audit where (file_name like '%abc%' or file_name like '%dce%') and substr(file_name,17,8)=to_char(to_date(sysdate-2,'DD/MM/YY'), 'yyyymmdd') > asa_file_count.log)
daybefore=`TZ=aaa48 date +%d-%m-%Y`
if [[ $count -lt 20 ]]
then
echo "Alert - Source files are yet to be received for date: $daybefore" | mail -s "Alert : Source data files missing" s#g.com
fi
Parentheses are special to the shell. Your SQL script contains parentheses you don't want the shell to process. However, the shell processes all non-quoted parentheses. Therefore, you can use quotes to prevent the parentheses in your SQL from being interpreted by the shell:
count=$(sqlplus $PROD_DB "#select count(*) from file_audit where (file_name like '%abc%' or file_name like '%dce%') and substr(file_name,17,8)=to_char(to_date(sysdate-2,'DD/MM/YY'), 'yyyymmdd')" > asa_file_count.log)
# ^ and similarly, a closing quote at the end, just before ">asa_file..." .
Now, there is a second issue: you have
count=$(sqlplus ... > asa_file_count.log)
However, I think this means count will always be empty, since the count will go into asa_file_count.log and will not be available to be captured with $(). I believe removing the >asa_file_count.log will probably do what you want:
count=$(sqlplus "$PROD_DB" "<your query>")
(I also put double-quotes around $PROD_DB just in case PROD_DB's value contains any spaces.)

Output showing too early

I made a small Bash-script to make my life easier. But I encountered a problem which I can't fix.
What I want
I've made a small script which will check for php-errors in a file each time that file gets saved/changed. This is done without me needing to run a command each time. So I run the Bash-script once on my second screen, and than each time when I save my PHP-file on screen one; I get the eventual errors shown on screen two automatically.
Basic algorithm
Get the hash of the file
Compare it to it's previous hash
If it differs, the file is changed/saved: Check if there are errors using the php -l command
Print out the result from php -l
Problem:
The result from php -l gets printed out before my code asked for it.
Code
#!/bin/bash
#Declaring basic variables here
fileToCheck="$1"
oldHash=("")
checksum=("")
#Function to get a striped line as long as the terminal width
function lineAmount {
cwidth=`tput cols`
lines=""
for i in $(seq $(expr $cwidth - 33)); do lines="$lines-";done
echo $lines
}
#Function to show the actual error
function showError {
msg=$1
time=`date +"%c"`
l=$(lineAmount)
if [ "$msg" == "No" ]
then
msg="No errors detected."
fi
printf "\n\n$time $l \n$msg\n"
}
#Start-screen------------------------------------------------
printf "Starting session for $1 at $time \n$(lineAmount)\n"
if [ ! -f $1 ]
then
echo "[Error] File $1 not found."
exit
fi
printf "\n\n\n"
#------------------------------------------
#Printing out error when file changed
while true
do
sleep 0.6
checksum=($(sha256sum $fileToCheck))
checksum=${checksum[0]}
if [ "$checksum" != "$oldHash" ]
then
error=$(php -l $fileToCheck)
oldHash=$checksum
showError $error
fi
done
Test file (test.php):
<?php
function foo() {
}
?>
Output of script:
Starting session for /home/name/Desktop/test.php at
-----------------------------------------------
Thu 11 Aug 2016 08:16:15 PM CEST -----------------------------------------------
No errors detected.
Now, in test.php I delete line 4:
<?php
function foo() {
?>
This will of course give an error, and my script shows that error:
Starting session for /home/name/Desktop/test.php at
-----------------------------------------------
Thu 11 Aug 2016 08:16:15 PM CEST -----------------------------------------------
No errors detected.
PHP Parse error: syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6
Thu 11 Aug 2016 08:19:37 PM CEST ----------------------------------------------------------------------------------
Parse
But like you can see, this is not a nice output.
PHP Parse error: syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6 should be printed below the second dotted line. Not below "No errors found." (The first output).
Expected output:
Starting session for /home/name/Desktop/test.php at
-----------------------------------------------
Thu 11 Aug 2016 08:16:15 PM CEST -----------------------------------------------
No errors detected.
Thu 11 Aug 2016 08:19:37 PM CEST ----------------------------------------------------------------------------------
PHP Parse error: syntax error, unexpected end of file in /home/name/Desktop/test.php on line 6
I tried a lot, I tried to change my algorithm a bit, searched up a lot; but it ain't working.
I guess the problem is somewhere on line 51, or 29. But I really can't see what's wrong.
Thanks!
Here's a stripped down and simplified version of your problem:
Why does this print an error message immediately instead of assigning it to the variable?
$ error=$(php -l test.php)
PHP Parse error: syntax error, unexpected end of file in test.php on line 5
php -l prints error messages to stderr like a good Unix citizen should. $(..) only captures stdout.
If you want to capture stdout and stderr together, you can use:
error=$(php -l $fileToCheck 2>&1)
You should also quote your variables so that the message is passed as a single parameter, since you're currently throwing away most of it (shellcheck is helpful):
showError "$error"
Being a good citizen, php also returns a useful exit code, so instead of trying to match a "No" to see if it's successful, you can just check the status directly:
if error=$(php -l $fileToCheck 2>&1)
then
echo "No problems"
else
echo "It failed with these messages: $error"
fi

Add input to an existing file with Bash

I am working on a library record app (for school).
I need to be able to collect user input and write to an existent file (add new record). However, when I try to do so, I get the following error:
./minilib.sh: line 12: : No such file or directory
Here is my function for adding new records
records = "/lib_records.txt"
add_book(){
echo
echo "Enter Book Name:"
read name
echo "Enter Book Author:"
read author_name
echo "$name $author_name" >> "$records" #this is my line 12
}
Any idea what may be causing the error? Any help is greatly appreciated.
Here are the file permissions:
-rwxrwxrwx. 1 GSUAD\ GSUAD\domain^users 0 Oct 30 18:04 lib_records.txt
-rwxrwxrwx. 1 GSUAD\ GSUAD\domain^users 1253 Oct 30 18:40 minilib.sh
Here are 2 issues for your shell script:
records="./lib_records.txt": should not have space before and after =
"./lib_records.txt" instead of "/lib_records.txt"
Here is modified script for you.
records="./lib_records.txt"
add_book(){
echo
echo "Enter Book Name:"
read name
echo "Enter Book Author:"
read author_name
echo "$name $author_name" >> "$records" #this is my line 12
}
add_book
You shouldn't store file in / directory (/lib_records.txt), because you will probably get a Permission denied error. Secondly, remove spaces in the first line.

How a function should exit when it called with here-document from shell script?

I have a COBOL program which should be run thru shell script and should accept the values from the here document. in the here document, i should call a function that should let control to be exit abnormally with exit code.
I have tried as below but it is not working for me.
This is my COBOL program:
01 WW-ANS PIC X value space.
IRS-200.
display "ARE THE ABOVE ANSWERS CORRECT? Y/N/E".
Accept ws-ans.
display "entered value is " ws-ans "<".
IF WW-ANS = "E" or "e"
PERFORM STOP-RUN-CA.
IF WW-ANS NOT = "Y" AND "N" AND "E"
and "y" and "n" and "e"
PERFORM DISPLAY-01 THRU DISPLAY-01-EXIT
GO TO IRS-200.
IF WW-ANS = "Y" or "y"
display "Program executed successfully"
PERFORM STOP-RUN-CA.
ELSE
GO TO IRS-200.
DISPLAY-01.
DISPLAY "value is >" WW-ANS "<".
DISPLAY "INVALID RESPONSE".
This is my shell script:
#!/bin/bash
funexit ()
{
echo "calling funexit"
exit 1
}
/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:
Output is:
[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is c<
value is >C<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully
When ever function gets called from here document the COBOL program accept the value as "C", since at function: it invoke the echo command and considering the first character from the "calling funexit" string, instead of getting exit.
From the function, I have removed echo statement like below:
#!/bin/bash
funexit ()
{
exit 1
}
/caplus/pub/test123<<:EOD:
1
g
$(funexit)
Y
:EOD:
Output is:
[Linux Dev:adminusr ~]$ ./test123.sh
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is 1<
value is >1<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is g<
value is >G<
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is <
value is > <
INVALID RESPONSE
ARE THE ABOVE ANSWERS CORRECT? Y/N/E
entered value is Y<
Program executed successfully.
When ever function gets called from here document the COBOL program accept the value as spaces instead of getting exit.
The script should get exit abnormally with some exit code.
This example looks contrived because you are giving it both static input. However, that is probably because this is just a simplified example.
I guess is that you want funexit to return the E so that the input would mean that there is no more input, and nothing if there is more input. To be clear, the funexit script is called (and finishes) before COBOL is called.
I think you would want to code your shell script like this:
#!/bin/bash
funexit ()
{
echo calling funexit 1>&2
echo E
}
/caplus/pub/test123<<:EOD:
1
g
$(funexit)Y
:EOD:
Notice that the call to funexit and the following Y are on the same line. That way, if funexit did not return anything, the cobol program would not see a blank line. If funexit returns an E (actually an E followed by a new line) it would see the E.
Also notice that your debugging output of "Calling funexit" is redirected to standard error; before it was being sent to the cobol program and it ACCEPTed the letter C (from "Calling").
And lastly, the funexit script does not need to exit, as that is what will happen at the end of the script anyway.
#ANR;
Use ACCEPT ... ON EXCEPTION
Ala
identification division.
program-id. sample.
data division.
working-storage section.
01 the-fields.
05 field-one pic x(8).
05 field-two pic x(8).
05 field-three pic x(8).
05 field-four pic x(8).
*> ***************************************************************
procedure division.
accept field-one end-accept
display field-one end-display
accept field-two end-accept
display field-two end-display
accept field-three
on exception
display "no field three entered" end-display
not on exception
display field-three end-display
end-accept
accept field-four
on exception
display "no field four entered" end-display
not on exception
display field-four end-display
end-accept
goback.
end program sample.
So a run with four lines of input looks like
./sample <fourdatums.txt
one
two
three
four
and with only three
./sample <threedatums.txt
one
two
three
no field four entered
Since funexit is executed in a subshell created by the command substitution, you'll need to check its exit status outside the here document to determine if the parent shell should exit.
#!/bin/bash
funexit () {
echo "calling funexit"
exit 1
}
output=$(funexit) || exit
/caplus/pub/test123<<:EOD:
1
g
$output
Y
:EOD:
Assign the output of your function to a variable outside the heredoc and check for failure there:
#!/bin/bash
funexit ()
{
exit 1
}
if ! funexitvalue=$(funexit) ; then
echo "Failure!"
exit 1
fi
/caplus/pub/test123<<:EOD:
1
g
$funexitvalue
Y
:EOD:
This will prevent the COBOL program to be run if funexit does not exit successfully.
Explanation:
Command substitutions ($(...)) in bash always "work", as in, the substitution is replaced by the output of the command. Even if the command exits with an error:
$ echo "$(echo foobar; exit 1)"
foobar
$ echo $?
0
As you can see, the first echo exits successfully, even though the command in the substitution failed. The return code of the command substitution does not affect the actual command in any way.
In contrast:
$ a="$(echo foobar; exit 1)"
$ echo $?
1
$ echo $a
foobar
Here the return code of the command substitution is not shadowed by any other command, so you can actually check, if it returned successfully. Anyway, the assignment of the output to a was still successful.
Note: If you intended the COBOL program to be run up to the point where the faulty input would happen, than heredocs are not the way to go, as they are completely evaluated before they are even passed to the program. So with heredocs it is an all or nothing deal.
The heredoc is going to be parsed by the shell and passed as input in its entirety, and your approach is not going to work. However, you can certainly break up the input:
{ cat << EOF
This text will always be entered to the test123 executable;
EOF
funexit # exit or return, as needed
cat << EOF
If funexit returned, this will go to test123.
If funexit exited, it will not
EOF
} | caplus/pub/test123

Resources