金髪の瞬間を過ごしていました。
問題の説明: したがって、ファイルにランダムな間隔で継続的に更新されるタイムスタンプを持つデータがあり、以前の合計時間のデータをフィルタリングしたいと思います(つまり、現在の時刻が14:35の場合は13時の期間を意味します。) 14:00、同様に時間が00:03の場合、23:00~00:00です。このデータを取得したら、それをmysqlテーブルに送信したいと思います。完了すると、crontabを使用して自動的に実行されます。
私が達成したいもの: 理想的には、過去のデータを取得してmysqlテーブルに送信したいと思います。その時間に何もない場合は、「この間は更新がありません」というメッセージを送信したいと思います。したがって、本質的にこれはif / elseステートメントだと思います。新しいものがある場合はこれを行い、そうでない場合は更新しないでください。しかし、これはうまくいきません。
私の考えで何が起こっているのか: コードは過去の合計時間を確認し、それをmysqlテーブルに送信します。しかし、他の記録もすべて確認しますが、古い記録は過去1時間以内ではないため、「その他」カテゴリに入り、「この期間中は更新がありません」というメッセージがたくさん出てきます。尋ねる:どうすればこれ以上行くことができますか?
私のコードは次のとおりです(いくつかの項目を削除したため、構文上正確ではない可能性があります)。
#!/bin/bash
#---------------------------------------------------------------------------------
# Adds all the transactions for the past full hour into a log file
# named log.csv
# input file: mqtt.csv
# output file: outfile.csv
#
#
#
#---------------------------------------------------------------------------------
current_time_hr=`date +%H` #Get the current hour only
current_time_date=`date +%F` #Get the full date YYYY-MM-DD
current_time_full=$current_time_date' '$current_time_hr':00:00' #Concatenate the date & current hour
current_time=`date -d "$current_time_full" +%s` #convert the time to seconds
echo "$current_time" #Print out
period=3600 #3600 seconds = 60 min = 1 hour
one_hr_before=$((current_time-period)) # subtrace one hour in seconds - to get one hour ago in seoonds
echo $one_hr_before #Print out
count=0 #Initialize the counteR
log=log.txt
out_file_name=outfile.csv #Output file
`rm -f $out_file_name` #Rmv to avoid appending
#Filter below
cat /DIR/SOME_DIR/mqtt.csv | grep SX | grep ',scan' | grep -v 'HDCU.*HDCU' | grep -v 'Sensor,Module' | grep '^[0-9]*,e,gf,STACKEXCHANGEe,HDCU.*,d,scan,.*,.*,.*,.*,.*,.*' | sed 's/,H[0-9][0-9]/,/g' | tail -n100 >>$out_file_name
cat $out_file_name | ( while read line
do
echo $line #Print out
#-----
# This is to convert $line into an array named "awk_var_array"
#----- ----- ----- ----- ----- ---------- ----- ---------- ----- -----
IFS=","
read -a awk_var_array <<< "${line}"
record_time=${awk_var_array[0]}
container=${awk_var_array[4]}
time_date=`date -d "@$record_time" +%F`' '`date -d "@$record_time" +%T`
no_array_less_one=$((${#awk_var_array[@]}-2))
#-----------
# Var is created & initialized; And is used to concatenate machine name parts
# in the consequtive fields before direction (IN/OUT) field
#----------
var=""
k=$((${#awk_var_array[@]}-1)) # k is the last element of the array
j=11 # j is the element where the part name starts
while [ $j -lt $k ] # do a for a loop with while
do
echo "j:$j k:$k ${awk_var_array[$j]}"
new_var=${awk_var_array[$j]}
var=$var' '$new_var
j=$((j+1))
done
part_name=${var:1} #gets rid of the first character as this is a ' ';
echo -e "\t\t\t\t\t\t\tvar $part_name"
count=$((count+1)) #Increase counter
echo "c-o-u-n-t $count" #Print out
full_date=`date -d "@$record_time" +%F`' '`date -d "@$record_time" +%T`
echo "FD:$full_date"
scan_id=${awk_var_array[9]}
dir=${awk_var_array[$k]}
dir=`echo $dir | sed 's/*//g'`
echo "FD:$full_date, SID:$scan_id, PartName:$part_name, DIR:$dir"
if [ "$record_time" -lt "$current_time" ] && [ "$record_time" -ge "$one_hr_before" ] #Bouncries for permissible data count
then
dbq="INSERT INTO mytable.table (time, part_number, direction, stock_point_name, scan_id, ignored) VALUES ('$time_date', '$part_name', '$dir', '$container', '$scan_id', '0');"
else
dbq="INSERT INTO mytable.table (part_number) VALUES ('there is no updates this hour');"
fi
mysql -uUSER -p'PASSWORD' << EOF
$dbq
EOF
done
echo "count: $count" #Print out
time_stamp_date=`date +%F` #Get date
time_stamp_time=`date +%T` #Get time
time_stamp=$time_stamp_date' '$time_stamp_time #Concatenate current DATE TIME then print out to log.csv file
printf "%20s;%8d;records added\n" "$time_stamp" "$count" >>$log )
答え1
ロジックを少し更新し、ループ内に実際に追加された行数を数えるだけです。データが追加されない場合は、ループの外側に「何もしない」メッセージを追加します。
これは擬似コードです:
counter = 0
for each line
if date in range
insert data
increment counter
else
# do nothing
fi
done
if counter > 0
# some lines were imported, nothing more to do
else
insert 'no updates' message
fi
各行に対して新しいデータベース接続を開くことは非常に非効率的です。かなり大きなデータブロックを取得する必要がある場合は、コードをさらにリファクタリングする必要があります。つまり、メインループで.sql
すべての挿入ステートメントを含むファイルをビルドし、ループの直後(理想的にはトランザクション内で)を実行します。または、挿入を生成しないで、適切な形式でデータを生成します。LOAD DATA INFILE
。