Shell Script fixed space issues - shell

I am trying to create a file with a header as well as some extracts from the input files.. I am always getting space alignment issues through I am using fixed space..
Any advise pls.. Thanks, here is the sample code
# print header
printf '%-50s | %-30s | %-30s | %-30s | %-30s | %-30s %-5s \n' "FileName" "Amount Rec" "Payments" "Total Adjustments" "Adjustment Amount" "File Date" "|" >> $msgfile
for file in "$SEARCH_DIR"/*; do
file=`basename "$file"`
recamt=$(awk -F "*" '/BPR/{print $3}' $file)
amount1=$(awk -F "*" '/TS3/{print $5}' $file)
amount1=$(awk -F "*" '/PLB/{print $7}' $file)
printf '%-50s | %-30s | %-30s | %-30s | %-30s | %-30s %-5s \n' "$file" "$recamt" "$amount1" "1" "$amount1" "$weekdate" "|" >> $msgfile
The output when I open it in notepad looks good, but when I send this as a email ( mailx), I see space issues the output.. Any thoughts ?
My output values as below..
xxxxxxx.xxxxx.xxxxxxxxx.txt | 906262.23 | 393 | 1 | 75297.4 | 06-Mar-2019 |

Related

Dealing with linebreaks in while read line

Maybe I'm using the wrong tool for the job here...
My data looks like this (this is from a json file which has been converted to a csv):
"hostname1",1,""
"hostname2",1,""
"hostname3",0,"yay_some_text
more_text
more_text
"
The first column is the hostname, second is the exit code and the third the result. I usually do something like this and make a moderately pretty table:
cat tmp.file | ( while read line
do
name=$(echo $line | awk -F "," '{print $1}')
exit_code=$(echo $line | awk -F "," '{print $2}')
output=$(echo $line | awk -F "," '{print $3}')
#I can then do stuff with the output here and ultimately do this:
echo -e "|${name}\t|${exit_code}\t|${output}\t|"
done
)
However the third column is causing me no end of problems; I think regardless of what I do, the read line bit will make this impossible. Does anyone have a better method of sorting this? I'd ideally like to keep the linebreaks, but if thats going to be too hard, I'll happily replace them with commas.
Desired output (either is fine):
| hostname1 | 1 | |
| hostname2 | 1 | |
| hostname3 | 0 | yay_some_text
more_text
more_text |
| hostname1 | 1 | |
| hostname2 | 1 | |
| hostname3 | 0 | yay_some_text, more_text, more_text |
Whichever of these you prefer will work robustly* and efficiently using any awk in any shell on every UNIX box:
$ cat tst.awk
{ rec = rec $0 ORS }
/"$/ {
gsub(/[[:space:]]*"[[:space:]]*/,"",rec)
gsub(/,/," | ",rec)
printf "| %s |\n", rec
rec = ""
}
.
$ awk -f tst.awk file
| hostname1 | 1 | |
| hostname2 | 1 | |
| hostname3 | 0 | yay_some_text
more_text
more_text |
.
$ cat tst.awk
{ rec = rec $0 RS }
/"$/ {
gsub(/[[:space:]]*"[[:space:]]*/,"",rec)
gsub(/,/," | ",rec)
gsub(RS,", ",rec)
printf "| %s |\n", rec
rec = ""
}
.
$ awk -f tst.awk file
| hostname1 | 1 | |
| hostname2 | 1 | |
| hostname3 | 0 | yay_some_text, more_text, more_text |
*robustly assuming your quoted strings never contain commas or escaped double quotes, i.e. it looks like the example you provided and your existing code relies on.
$ gawk -v RS='"\n' -v FPAT='[^,]*|"[^"]*"' -v OFS=' | ' '
{gsub(/"/,""); $1=$1; print OFS $0 OFS}' file
| hostname1 | 1 | |
| hostname2 | 1 | |
| hostname3 | 0 | yay_some_text
more_text
more_text
|
In your case, one way is , you can transform the file to a simpler structure before using
awk '/[^"]$/ { printf("%s", $0); next } 1' tmp.file | ( while read line
do
name=$(echo $line | awk -F ',' '{print $1}')
exit_code=$(echo $line | awk -F ',' '{print $2}')
output=$(echo $line | awk -F ',' '{print $3}')
#I can then do stuff with the output here and ultimately do this:
echo -e "|${name}\t|${exit_code}\t|${output}\t|"
done
)
If all you want to do is to display as a table, you can use column utility
awk '/[^"]$/ { printf("%s", $0); next } 1' tmp.file | column -t -o " | " -s ,
If you are so particular about the starting and ending seperator '|', you can simply pipe the output of this command to a sed|awk.

how to read words from a file using shell script

i have a file /ws/$1-rcd/temp.txt which has only one line as follows
198|/vob/ccm_tpl/repository/open_source/commons_collections/3_2_2/...
i have a script to get the value repository/open_source/commons_collections and 3_2_2 by reading the file and looping through it using for loop
i have my code as follows
grep -n "$4" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f1,2 | sed -e 's/\:element/|/g' | sed -e 's/ //g' > /ws/$1-rcd/temp.txt
for i in `cat /ws/$1-rcd/temp.txt`
do
line=`echo $i | cut -d"|" -f1`
path=`echo $i | cut -d"|" -f2`
whoami
directory_temp=`echo $path | awk -F "/" '{ print $(NF-2)}'`
if [ "$directory_temp" == "$4" ]
then
OLD_VERSION=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | awk -F "/" '{ print $(NF-1)}'`
total_fields=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | awk -F "/" '{ print NF }'`
dir_path=`expr ${total_fields} - 2`
loc=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | cut -d"/" -f1-"${dir_path}"`
location=`echo $loc | cut -d"/" -f4,5,6`
fi
done
but when i run this code it gives me an error as
-bash: line 45: syntax error near unexpected token |'
-bash: line 45:for i in 198|/vob/ccm_tpl/repository/open_source/commons_collections/3_2_2/...'
can anyone please suggest what am i doing wrong
If you want to iterate through each line of a file, use while loop like below
while read -r line ;do
echo $line
done <file.txt
so, your code can be rewritten as
grep -n "$4" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f1,2 | sed -e 's/\:element/|/g' | sed -e 's/ //g' > /ws/$1-rcd/temp.txt
while read i ; do
line=`echo $i | cut -d"|" -f1`
path=`echo $i | cut -d"|" -f2`
whoami
directory_temp=`echo $path | awk -F "/" '{ print $(NF-2)}'`
if [ "$directory_temp" == "$4" ]
then
OLD_VERSION=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | awk -F "/" '{ print $(NF-1)}'`
total_fields=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | awk -F "/" '{ print NF }'`
dir_path=`expr ${total_fields} - 2`
loc=`sed -n "${line}p" /ws/$1-rcd/raw-vobs-config-spec | cut -d " " -f2 | cut -d"/" -f1-"${dir_path}"`
location=`echo $loc | cut -d"/" -f4,5,6`
fi
done < /ws/$1-rcd/temp.txt
You may be better served relying on parameter expansion and substring removal. For example:
#!/bin/sh
a=$(<dat/lline.txt) ## read file into a
a=${a##*ccm_tpl/} ## remove from left to ccm_tpl/
num=${a##*collections/} ## remove from left to collections/
num=${num%%/*} ## remove from right to /
a=${a%%${num}*} ## remove from right to $num
Input File
$ cat dat/lline.txt
198|/vob/ccm_tpl/repository/open_source/commons_collections/3_2_2/..
Output
$ sh getvals.sh
a : repository/open_source/commons_collections/
num : 3_2_2
If you need to trim in some other way, just let me know and I'm happy to help further.

Shell Scripting command not found Error

I'm new to programming with shell and want to ask what is wrong with my code?
#!/bin/bash
#DHT11
SCRIPT="/var/www/ErnestynoFailai/scripts/DHT 11 4"
#DHT22
#SCRIPT="/root/to/folder/DHT 22 4"
#AM2302
#SCRIPT="/root/to/folder/DHT 2302 4"
HUMIDITY=`$SCRIPT | grep "Temp" | awk -F " " '{print $7}'`
TEMPRATURE=`$SCRIPT | grep "Temp" | awk -F " " '{print $3}'`
#-a = AND = &&
while [ $HUMIDITY=="" -a $TEMPRATURE=="" ]
do
$HUMIDITY=`$SCRIPT | grep "Temp" | awk -F " " '{print $7}'`
$TEMPRATURE=`$SCRIPT | grep "Temp" | awk -F " " '{print $3}'`
done
echo "$HUMIDITY"
echo "$TEMPRATURE"
I'm getting:
line 14 or 15 =26: or =: command not found...
There are two problems:
These lines are not returning anything, or at least a string:
HUMIDITY=`$SCRIPT | grep "Temp" | awk -F " " '{print $7}'`
TEMPRATURE=`$SCRIPT | grep "Temp" | awk -F " " '{print $3}'`
This is causing =: command not found errors.
Your while condition needs to be
while [[ $HUMIDITY == "" && $TEMPRATURE == "" ]]
Finally, while not causing problems, TEMPERATURE is misspelled, which might cause you grief later on.
Variables have to be assigned without leading $:
HUMIDITY=`$SCRIPT | grep "Temp" | awk -F " " '{print $7}'`
TEMPRATURE=`$SCRIPT | grep "Temp" | awk -F " " '{print $3}'`

unexpected EOF while looking for matching ``'

I try to run this script to create simple, beautiful windows with bushcurses but there is an error
~/bashcurses$ ./myfirstwindow1.sh
./myfirstwindow1.sh: line 32: unexpected EOF while looking for matching ``'
./myfirstwindow1.sh: line 39: syntax error: unexpected end of file
I have tried to add or delete '" but cannot find proper solution. Can you please help me to identify the cause of the error?
script:
#!/bin/bash
. `dirname $0`/simple_curses.sh
main (){
window "`hostname`" "red"
append "`date`"
addsep
append_tabbed "Up since|`uptime | cut -f1 -d"," | sed 's/^ *//' | cut -f3- -d" "`" 2 "|"
append_tabbed "Users:`uptime | cut -f2 -d"," | sed 's/^ *//'| cut -f1 -d" "`" 2
append_tabbed "`awk '{print "Load average:" $1 " " $2 " " $3}' < /proc/loadavg`" 2
endwin
window "Memory usage" "red"
append_tabbed `cat /proc/meminfo | awk '/MemTotal/ {print "Total:" $2/1024}'` 2
append_tabbed `cat /proc/meminfo | awk '/MemFree/ {print "Used:" $2/1024}'` 2
endwin
window "Processus taking memory and CPU" "green"
for i in `seq 2 6`; do
append_tabbed "`ps ax -o pid,rss,pcpu,ucmd --sort=-cpu,-rss | sed -n "$i,$i p" | awk '{printf "%s: %smo: %s%%" , $4, $2/1024, $3 }'`" 3
done
endwin
window "Last kernel messages" "blue"
dmesg | tail -n 10 > /tmp/deskbar.dmesg
while read line; do
append_tabbed "$line" 1 "~"
done < /tmp/deskbar.dmesg
rm -f /tmp/deskbar.dmesg
endwin
window "Inet interfaces" "grey"
ERROR >> _ifaces=$(for inet in `ifconfig | cut -f1 -d " " | sed -n "/./ p"`; do ifconfig $inet | awk 'BEGIN{printf "%s", "'"$inet"'"} /adr:/ {printf ":%s\n", $2}'|sed 's/adr://'; done)
for ifac in $_ifaces; do
append_tabbed "$ifac" 2
done
endwin
}
main_loop 1

I don't want array to do word splitting

Below is my code. But bash is doing word splitting therefore I have failure. How to make my script so that there is no word splitting.
namaSensor=$(sensors | egrep "°C" | awk '{print $0}' | awk -F ':' '{print $1}')
for sensor in $namaSensor
do
if [ $(sensors | grep -c "$sensor") -ne 0 ]
then
currentTemperature=$(sensors | egrep "$sensor" | awk '{print $0}' | awk -F '+' '{print $2}' | cut -c 1-4 | awk -F '.' '{print $1}')
maxTemperature=$(sensors | egrep "$sensor" | awk '{print $0}' | awk -F '+' '{print $3}' | cut -c 1-4 | awk -F '.' '{print $1}')
if [ $currentTemperature -lt $maxTemperature ]
then
printf "current temperature is %d°C and the maximum allowed temperature is %d°C\n" "$currentTemperature" "$maxTemperature"
printf "temperature is within the maximum allowed temperature\n"
echo "$sensor"
else
printf "current temperature is %d°C and the maximum allowed temperature is %d°C\n" "$currentTemperature" "$maxTemperature"
printf "temperature is more than the maximum allowed temperature\n"
#exit 255
fi
fi
done.
This is the output of sensors for my unit.
acpitz-virtual-0
Adapter: Virtual device
temp1: +40.0°C (crit = +111.0°C)
temp2: +40.0°C (crit = +111.0°C)
coretemp-isa-0000
Adapter: ISA adapter
Physical id 0: +34.0°C (high = +87.0°C, crit = +105.0°C)
Core 0: +31.0°C (high = +87.0°C, crit = +105.0°C)
Core 1: +22.0°C (high = +87.0°C, crit = +105.0°C)
Please help
As I understand you have your array splitted as following:
Physical
id
0
and so on. To change this behaviour you need to change your Internal Field Separator (IFS) to a newline. So your code should look like this:
IFS=$'\n'
nameSensor=$(sensors | egrep "°C" | awk '{print $0}' | awk -F ':' '{print $1}')
for sensor in $nameSensor
do
if [ $(sensors | grep -c "$sensor") -ne 0 ]; then
currentTemperature=$(sensors | egrep "$sensor" | awk '{print $0}' | awk -F '+' '{print $2}' | cut -c 1-4 | awk -F '.' '{print $1}')
maxTemperature=$(sensors | egrep "$sensor" | awk '{print $0}' | awk -F '+' '{print $3}' | cut -c 1-4 | awk -F '.' '{print $1}')
if [ $currentTemperature -lt $maxTemperature ]; then
printf "current temperature is %d°C and the maximum allowed temperature is %d°C\n" "$currentTemperature" "$maxTemperature"
printf "temperature is within the maximum allowed temperature\n"
echo "$sensor"
else
printf "current temperature is %d°C and the maximum allowed temperature is %d°C\n" "$currentTemperature" "$maxTemperature"
printf "temperature is more than the maximum allowed temperature\n"
#exit 255
fi
fi
done

Resources