나는 금발의 순간을 보내고 있었다.
문제 설명: 따라서 파일에 임의의 간격으로 지속적으로 업데이트되는 타임스탬프가 있는 데이터가 있고 이전 전체 시간에 대한 데이터를 필터링하고 싶습니다(즉, 현재 시간이 14:35라면 13시 사이의 기간을 의미합니다. 00) -14:00, 마찬가지로 시간이 00:03이면 23:00-00:00입니다. 이 데이터를 얻은 후에는 이를 mysql 테이블로 보내고 싶습니다. 완료되면 crontab을 사용하여 자동으로 수행됩니다.
내가 달성하고 싶은 것: 이상적으로는 지난 시간의 데이터를 가져와서 mysql 테이블로 보내고 싶습니다. 해당 시간에 아무것도 없으면 "이 시간 동안 업데이트가 없습니다"라는 메시지를 보내고 싶습니다. 따라서 본질적으로 이것은 if/else 문이라고 생각합니다. 새로운 것이 있으면 이 작업을 수행하고 그렇지 않으면 업데이트하지 마십시오. 그러나 이것은 작동하지 않습니다.
내 생각에 무슨 일이 일어나고 있는지: 코드는 지난 전체 시간을 확인하고 이를 mysql 테이블로 보냅니다. 하지만 다른 기록도 모두 확인하는데, 오래된 기록은 지난 한 시간 내에 있지 않기 때문에 "기타" 범주에 들어가고 "이 시간 동안 업데이트가 없습니다"라는 메시지가 많이 나옵니다.묻다:어떻게 하면 이 이상으로 갈 수 있나요?
내 코드는 다음과 같습니다(몇 가지 항목을 제거했으므로 구문상 정확하지 않을 수 있습니다).
#!/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
.