Extract data from file with awk in bash script and store - bash

I am new here and also a starter on programming so please handel me with care .
Filename = Datafile.tmp
I get a log file with 1 line of data like this (comma seperated)
24092014,17:21,357.7,5.1,49.96,228.6,7.9,1757.5,3378200.0,28.2,20680.0,846.0,1800.0,2
Maby i must explain shomething. I have a script writing in BASH that read out the data from the inverter by inside routine. I want to change that script so it read data out of the data file like above. The script is verry long but a place only the reading part of it.
So i think i can del all the reading port routines and just focus on the
convert data from array into readable data in my case from file.
and at the bottum storing variables to working file
#Ask data from inverter
get_data() {
printf $GetDataCMD > $PORT
dd if=$PORT of=$OUT bs=1 count=$dataLengthTotal &
PID=$!
sleep 3
if [ -d /proc/$PID ]
then
rcvd="no"
kill $PID
else
rcvd="yes"
fi
}
#Put received data in array and check for errors
receive_data() {
(( dataLengthTotal = $ANS_OFFSET+$dataLengthOutput+1 ))
retry_counter=$RETRY
while (( retry_counter )); do
get_data < $PORT 2>/dev/null
if [ $rcvd = "yes" ]; then
data=(`od -b -v $OUT | sed -e 's/^[0-9]*//g' | sed -e 's/[ ]\([0-9]\)/ 0\1/g'`)
if [ ${#data[#]} -ne $dataLengthTotal ]; then
rcvd="nochk"
echo -e `date -R`": Wrong amount of data received\r" >> $LOG
init_comport
(( retry_counter -= 1 ))
else
# Check CRC
sumstr="${data[#]:$ANS_OFFSET:$dataLengthOutput}"
let sum=${sumstr// /+}
if ((sum%256 == data[9+$dataLengthOutput])); then
rcvd="chk"
retry_counter=0
else
rcvd="nochk"
echo -e `date -R`": Checksum error in received data\r" >> $LOG
init_comport
(( retry_counter -= 1 ))
fi
fi
else
init_comport
(( retry_counter -= 1 ))
fi
done
}
#convert data from array into readable data
get_current_data() {
dataLengthOutput=30
GetDataCMD=$GetCurrentDataCMD
receive_data
if [ $rcvd = "chk" ]; then
#errorbits
(( errbits = data[9+7] * 256 + data[9+6] ))
#Voltage Solarpanels (Usol)
(( Usol = data[9+9] * 256 + data[9+8] ))
#Current Solarpanels (Isol)
(( Isol = data[9+11] * 256 + data[9+10] ))
#AC Frequency (Fnet)
(( Fnet = data[9+13] * 256 + data[9+12] ))
#AC Voltage (Unet)
(( Unet = data[9+15] * 256 + data[9+14] ))
#AC Current (Inet)
(( Inet = data[9+17] * 256 + data[9+16] ))
#AC Power (Pnet)
(( Pnet = data[9+19] * 256 + data[9+18] ))
#Total delivered (Etot)
(( Etot = data[9+22] * 65536 + data[9+21] * 256 + data[9+20] + WtotOffset ))
#Temp Inverter (Tinv)
(( Tinv = data[9+23] ))
#Total runtime (Htot)
(( Htot = data[9+26] * 65536 + data[9+25] * 256 + data[9+24] + HtotOffset ))
#Total CO2 (Ctot)
(( Ctot = Etot * $CO2perc / 100 ))
fi
}
#check, convert and write error messages
convert_errorbits() {
ErrorStr="Systeem_OK"
if (( errbits )); then
if (( errbits & 0x01 )); then
ErrorStr="Usolar too high (`print_float $Usol 1` V). ${ErrorStr}"
fi
if (( errbits & 0x02 )); then
ErrorStr="Usolar too low (`print_float $Usol 1` V). ${ErrorStr}"
fi
if (( errbits & 0x04 )); then
ErrorStr="No mains detected. ${ErrorStr}"
fi
if (( errbits & 0x08 )); then
ErrorStr="Uac too high (${Unet} V). ${ErrorStr}"
fi
if (( errbits & 0x10 )); then
ErrorStr="Uac too low (${Unet} V). ${ErrorStr}"
fi
if (( errbits & 0x20 )); then
ErrorStr="FreqAC too high (`print_float $Fnet 2` Hz). ${ErrorStr}"
fi
if (( errbits & 0x40 )); then
ErrorStr="FreqAC too low (`print_float $Fnet 2` Hz). ${ErrorStr}"
fi
if (( errbits & 0x80 )); then
ErrorStr="Temperature error (${Tinv}ÂșC). ${ErrorStr}"
fi
if (( errbits & 0x100 )); then
ErrorStr="Hardware error. ${ErrorStr}"
fi
if (( errbits & 0x200 )); then
ErrorStr="Starting. ${ErrorStr}"
fi
if (( errbits & 0x400 )); then
ErrorStr="Max output (${Pnet} W). ${ErrorStr}"
fi
if (( errbits & 0x800 )); then
ErrorStr="I max (`print_float $Isol 2` A). ${ErrorStr}"
fi
echo -e `date -R`": Error message: $ErrorStr\r" >> $LOG
fi
}
#Get current day output
get_current_day() {
dataLengthOutput=8
(( daynr = 0 ))
(( crc = $GetDailyDataCRC+$daynr ))
GetDataCMD=$GetDailyDataCMD1\\x`printf "%02X" $1 $daynr`$GetDailyDataCMD2\\x`printf "%02X" $1 $crc`
receive_data
if [ $rcvd = "chk" ]; then
# Profit [kWH]
(( Etoday = data[9+7] * 256 + data[9+6] ))
# Runtime [h:mm]
(( Htoday = data[9+5] * 5 ))
# CO2
(( CO2 = Etoday * $CO2perc / 100 ))
fi
}
# Main Program
main(){
#set time variables
MTIME=`date +%M`
HTIME=`date +%H`
# Configure serial port
init_comport
#Store file contains data needed for calculating totals etc
#Internally an array is used, values are:
#0=Active flag
#1=WtotAct
#2=HtotAct
#3=WtotLog
#4=HtotLog
#fill array
store=(`cat $STORE`)
get_current_data
if [ $rcvd = "chk" ]; then
if (( ! store[0] )); then
echo -e `date -R`": Waking up; Inverter started.\r" >> $LOG
store[0]=1
if (( USE_30DAYS )); then
get_last_30_days
fi
if [ ! -f $PVDIARYCSV ]
then
create_pvdiary
fi
if (( USE_EMAIL )) && (( USE_EMAwake )); then
email_send "Bericht van uw zonnepanelen : ontwaken." "I'm awake now !\n\nUw Mastervolt Omvormer\n"
fi
fi
# Remember 'old-values' for calculating PVDiary inputs
(( store[5] = store[1] ))
(( store[6] = 0 ))
# Put total values into array for calculating daily profit
store[1]=$Etot
store[2]=$Htot
convert_errorbits
get_current_day
create_actual_page
rrd_update
fill_pvdiary
fill_sql
pvoutput_live_update
fi
#Write message before sleep
if [ $rcvd = "no" ] && (( ! retry_counter )) && (( store[0] )); then
echo -e `date -R`": No reaction from Inverter; entering sleep\r" >> $LOG
create_offline_page
store[0]=0
fi
#Write 0-values in PVDiary-file
if [ $rcvd = "no" ] && (( ! retry_counter )) ; then
(( store[5] = store[1] ))
(( store[6] = 0 ))
fill_pvdiary
(( store[5] = store[1] ))
(( store[6] = 0 ))
fill_sql
(( store[5] = 0 ))
fi
#Run timebased scripts (internal cron)
if [ $HTIME = 23 ] && [ $MTIME = 00 ]; then
fill_csv
fi
if [ $MTIME = 00 ] && (( USE_RRD )); then
graph
fi
if [ $MTIME = 00 ] && (( store[0] )) && (( USE_EMAIL )) && (( USE_EMAhour )); then
email_send_actual "Bericht van uw zonnepanelen : productie tot nu toe."
fi
#storing variables to working file
echo ${store[0]} ${store[1]} ${store[2]} ${store[3]} ${store[4]} ${store[5]}${store[6]}> $STORE
}
#What to do ?
case $1 in
"help" ) help;;
"create" ) create;;
"draw" ) graph;;
* ) main;;
esac

$ awk -F, '{print "Today = " $1 "\nTime = " $2 "\nHertz = " $5}' file
Today = 24092014
Time = 17:21
Hertz = 49.96

Related

Problem in shell code to find happy prime number

This is my code to find happy prime number, I don't know why it is giving error.
#!/bin/bash
happy(){
rem = $0
sum = $0
while [ $result -gt 0 ];
do
rem = $((result%10))
p = $((rem*rem))
sum = $((sum + p))
result = $((result/10))
done
return $sum
}
echo "Enter a number"
read num
for (( i=1; i<101; i++ ))
do
result=$i
while [ $result -ne 0 && $result -ne 4 ];
do
happy $result
done
if [ $?==1 ]
then echo "happy number"
else
echo "not a happy number"
fi
done
I see lots of syntax errors and some logical errors in your script.
This should be a fixed version (works at least for 13 and 4 :))
Errors I've found:
rem = $0 and similar: the spaces around assignments are not allowed in bash,
rem = $0: you assign a value that is never used,
rem = $0 and sum = $0 the first argument passed to the function is $1 not $0,
the input number is assigned to num but never used,
the exit condition from the for and while loops is broken,
...
#!/bin/bash
happy()
{
result=$1
sum=0
while [ $result -gt 0 ]; do
rem=$(( result % 10 ))
p=$(( rem * rem ))
sum=$(( sum + $p ))
result=$(( result / 10 ))
done
echo "$sum"
}
echo "Enter a number"
read num
result=$num
for (( i=1; i<101; i++ )) do
result=$(happy $result)
if [ $result == 1 ]; then
echo "$num is a happy number"
exit
fi
done
echo "$num is not a happy number"

Count occurences of a special character in a file

I am writing a bash script that will count occurences of [], (), {}, '', "", `` and // so that i can debug other scripts for missing one of them.
Here is the code:
a=0; b=0; cc=0; d=0; e=0; f=0; g=0; h=0; i=0; j=0 # set default values
squote=`echo -e "\x27"`
dquote=`echo -e "\x22"`
while IFS= read -r -n1 c; do
[ "$c" == "[" ] && (( a++ ))
[ "$c" == "]" ] && (( b++ ))
[ "$c" == "(" ] && (( cc++ )) # i imported this line from another online script, is there a reason why the author avoids (( c++ )) ?
[ "$c" == ")" ] && (( d++ ))
[ "$c" == "{" ] && (( e++ ))
[ "$c" == "}" ] && (( f++ ))
[ "$c" == "\x27" ] && (( g++ )) # single quote
[ "$c" == "$dquote" ] && (( h++ )) # double quote
[ "$c" == '`' ] && (( i++ )) # back tick
[ "$c" == '/' ] && (( j++ )) # forward slash
done < "$1"
echo '[]'="$a,$b"
echo '()'="$cc,$d"
echo '{}'="$e,$f"
echo "$squote" ="$g"
echo "$dquote" ="$h"
echo '``'="$i"
echo '/'="$j" # when used this way: /hello/
Questions:
1) why the cc++ instead of c++
2) why some results don't come out right at all.
3) How to annotate the special characters the right way.
Thank you in advance for your help.
some simplifications and functional script
#!/bin/bash
a=0; b=0; c=0; d=0; e=0; f=0; g=0; h=0; i=0; j=0
while read -r -n1 char; do
case "$char" in
"[" ) (( a++ )) ;;
"]" ) (( b++ )) ;;
"(" ) (( c++ )) ;;
")" ) (( d++ )) ;;
"{" ) (( e++ )) ;;
"}" ) (( f++ )) ;;
"'" ) (( g++ )) ;;
'"' ) (( h++ )) ;;
'`' ) (( i++ )) ;;
'/' ) (( j++ )) ;;
esac
done <<< "[]{}()/"$'\x60'$'\x22'$'\x27' # $'\x60' == backtick
echo '[]'="$a,$b"
echo '()'="$c,$d"
echo '{}'="$e,$f"
echo "'" ="$g"
echo '"' ="$h"
echo '`'="$i"
echo '/'="$j"
output
[]=1,1
()=1,1
{}=1,1
' =1
" =1
`=1
/=1
nota:
prefer: dquote=$( echo -e "\x22" ) # and not ``
better: dquote=$'\x22' # or \042 octal
simpler: dquote='"'
to check script and learn, I suggest to install shellcheck or use https://www.shellcheck.net/
initially:
[ "$char" == "[" ] && (( a++ ))
[ "$char" == "]" ] && (( b++ ))
[ "$char" == "(" ] && (( c++ ))
[ "$char" == ")" ] && (( d++ ))
[ "$char" == "{" ] && (( e++ ))
[ "$char" == "}" ] && (( f++ ))
[ "$char" == "'" ] && (( g++ ))
[ "$char" == '"' ] && (( h++ ))
[ "$char" == '`' ] && (( i++ ))
[ "$char" == '/' ] && (( j++ ))
but unnecessary tests are systematically performed.
we can also use:
if [[ $char == "[" ]]; then (( a++ ))
elif [[ $char == "]" ]]; then (( b++ ))
...
but performances with 10,000 iterations:
if > if elif > case
6720 ms > 2895 ms > 2073 ms

How to process value from for loop in shell

I have to a perform logic like this.
I have a array.
expression for this in shell
[(first no + arrlen) - ( index +1 ) - ge 10 ]
I have code this like this but it's not working
#!/bin/bash
array=(4 5 6 7 8 9)
for i in ${array[#]}
do
echo $i
done
echo "${#array[#]}"
l=${#array[#]}
count=0
for (( i=0; i < ${#array[#]}; i++ ))
do
if [ ($(`expr $i + $l`) - $(`expr ${!array[#]} + 1`)) -ge 10 ]
then
count=`expr $count + 1`
else
echo
fi
done
Your code could look like this:
#!/bin/bash
array=(4 5 6 7 8 9)
for i in "${array[#]}"; do
echo "$i"
done
length=${#array[#]}
first=${array[0]}
count=0
for (( i=0; i < length; i++ )); do
if (( (first + length) - (i + 1) >= 10 )); then
((count++))
else
echo "something"
fi
done
Don't use expr, use (( )) for arithmetic expressions
Quote expansions: "$i", "${array[#]}", ...
${!array[#]} expands to ALL indexes of your array, not the current index

Sum digits of a number while greater than 2 digits

The challenge is to sum the digits of a given number till the result has only one digit. Let say the number is "999" (9+9+9=27, 2+7=9). This is what I did till now.
#!/bin/bash
set +m
shopt -s lastpipe
NUMBER=999
DIGITS=`echo "${#NUMBER}"`
FINALSUM=0
if [ "$DIGITS" -gt 0 ] && [ "$DIGITS" -gt 1 ]; then
grep -o . <<< "${NUMBER}" | while read DIGIT; do
declare -x FINALSUM="$(($FINALSUM+$DIGIT))"
done
echo $FINALSUM
else
echo $SOMA
fi
A bit slow for large numbers:
function sumit {
i="$1"
while [ "$i" -gt 10 ]; do
(( i=i%10 + i/10 ))
done
echo "$1 => $i"
}
# Test
for i in 10 15 999 222 2229; do
sumit $i
done
Can an awk-ward guy join in?
$ awk -v i=999 '
BEGIN {
while( split(i,a,"") > 1) {
i=0;
for( j in a ) i+=a[j]
}
print i
}'
9

bash for with numerical comparison and file existence

I tried to do a for loop with 2 conditions but I didn't succeed in any way:
for (( i=0 ; -e /file && i < 10 ; i++ ))
of course I tried any combination of parentheses like:
for (( i=0 ; [ -e /file ] && [ i < 10 ] ; i++ ))
for (( i=0 ; [ -e /file -a i < 10 ] ; i++ ))
What's wrong on this?
I googled a lot for this, but I didn't find any suggestion.
You have to do some subshell trickery to pull this off:
for (( i=0 ; $([ -e /file -a $i -lt 10 ]; echo "$?") == 0; i++ ))
Or probably better:
for (( i=0 ; $([ -e /file ]; echo "$?") == 0 && i < 10; i++ ))
What's happening here is that $(...) is being run and placed into the mathematical expression ... == 0. When it's run the echo "$?" spits out the return code for [ which is 0 for no-error (i.e. expression is true), and 1 for error (i.e. expression is false) which then gets inserted as 0 == 0 or 1 == 0.

Resources