用awk在bash脚本和商店中从文件中提取数据
问题描述:
我是新来的,也是编程的入门者,所以请小心处理。用awk在bash脚本和商店中从文件中提取数据
Filename = Datafile.tmp
我得到一个日志文件与1号线这样的数据(逗号分隔)
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
莫比我必须解释shomething。我在BASH写了一个脚本,通过内部例程读取变频器的数据。我想更改该脚本,以便像上面那样从数据文件中读取数据。剧本很长,但只是阅读部分的地方。 所以我想我可以删除所有的阅读端口例程,只是专注于
将数组中的数据转换为我的情况下从文件中读取数据。 并在bottum存储变量到工作文件
#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
由于这是一个明白这一点。你使用打印命令给它一个名字,并获得第一个文件等等我可以把它直接放入一个变量或字符串?像$ Today和$ Time等等,所以我可以用它来覆盖bash脚本? – 2014-09-25 19:13:44
是的,但那肯定会是错误的做法。除非你操纵文件和流程,否则正确的做法就是用awk编写整个脚本。发表一个新的问题来描述你的样品输入和预期输出的大问题,所以我们可以帮你解决这个问题。 – 2014-09-25 19:24:10
我改变我的脚本maby你有一个建议? – 2014-09-25 20:28:55