Я написал сценарий для анализа файла журнала для университетского проекта, который требуется для работы на xubuntu 14.10. Скрипт отлично работает в Ubuntu и Windows Subsystem для Linux, но не в Xubuntu. После некоторой отладки я обнаружил, что сбой строки - это чтение:
IFS=${tab}
case ${line:0:2} in
"C${tab}")
read -r code customer_id time_supermarket time_queue\
changed_queues products_count <<< ${line}
...
Кажется, что чтение игнорирует IFS и использует новую строку в качестве разделителя, потому что оно копирует строку внутри кода переменной и не разделяет выполняется. Я предполагаю, что он распознает вкладку внутри строковой переменной, потому что она правильно соответствует "C${tab}"
в операторе case. Более того, если я печатаю "a${IFS}b
перед чтением, я получаю "a b"
.
Ниже приведен полный сценарий и небольшой образец тестовых случаев (обратите внимание, что stackoverflow заменяет вкладки пробелами, в моей системе есть табуляции между каждым значением и unix окончанием строки).
Спасибо всем, кто читает.
#!/bin/bash
file=./logs/supermarket.log
#use . (dot) in printf float even in systems
# that use , (comma) by default
LC_NUMERIC="en_US.UTF-8"
tab=$(printf '\t')
declare -a cashier_total_time_to_serve
declare -a cashier_total_time_open
declare -a cashier_elaborated_prodcuts
declare -a cashier_served_customers
declare -a cashier_closures_count
printf "Customers:\n"
printf "┌────────┬────────┬────────┬────────┬────────┐\n"
printf "│ ID │ #PRODS │SPRMTIME│SRVSTIME│ #QUEUE │\n"
printf "├────────┼────────┼────────┼────────┼────────┤\n"
while IFS=$'\n' read -r line; do
IFS=${tab}
case ${line:0:2} in
"C${tab}")
read -r code customer_id time_supermarket time_queue\
changed_queues products_count <<< ${line}
printf "│ %6d │ %6d │ %6.3f │ %6.3f │ %6d │\n" \
${customer_id} ${products_count} ${time_supermarket} \
${time_queue} ${changed_queues}
;;
"K${tab}")
read -r code cashier_id served_customers\
elaborated_products closures_count <<< ${line}
cashier_elaborated_prodcuts[${cashier_id}]=${elaborated_products}
cashier_served_customers[${cashier_id}]=${served_customers}
cashier_closures_count[${cashier_id}]=${closures_count}
;;
"KC")
read -r code cashier_id customer_id \
time_to_serve <<< ${line}
if [ -z "${cashier_total_time_to_serve[${cashier_id}]}" ]
then
cashier_total_time_to_serve[${cashier_id}]=0
fi
temp=$(echo ${cashier_total_time_to_serve[${cashier_id}]} + ${time_to_serve} | bc -l)
cashier_total_time_to_serve[${cashier_id}]=${temp}
;;
"KS")
read -r code cashier_id time_workshift <<< ${line}
if [ -z "${cashier_total_time_open[${cashier_id}]}" ]
then
cashier_total_time_open[${cashier_id}]=0
fi
temp=$(echo ${cashier_total_time_open[${cashier_id}]} + ${time_workshift} | bc -l)
cashier_total_time_open[${cashier_id}]=${temp}
;;
*)
;;
esac
done < $file
printf "└────────┴────────┴────────┴────────┴────────┘\n"
printf "\n"
printf "Cashiers: \n"
printf "┌────────┬────────┬────────┬────────┬────────┬────────┐\n"
printf "│ ID │ #PRODS │#CUSTMRS│OPENTIME│AVGSERVC│ #CLOSE │\n"
printf "├────────┼────────┼────────┼────────┼────────┼────────┤\n"
cashiers_count=${#cashier_closures_count[@]}
for (( i=0; i<$cashiers_count; i++ ))
do
cashier_avg_time_to_serve=$(echo ${cashier_total_time_to_serve[$i]} / ${cashier_served_customers[$i]} | bc -l)
printf "│ %6d │ %6d │ %6d │ %6.3f │ %6.3f │ %6d │\n" \
$i ${cashier_elaborated_prodcuts[$i]} \
${cashier_served_customers[$i]} ${cashier_total_time_open[$i]} \
$cashier_avg_time_to_serve ${cashier_closures_count[$i]}
done
printf "└────────┴────────┴────────┴────────┴────────┴────────┘\n"
KC 0 40 0.046
C 40 0.075 0.046 0 1
KC 0 12 0.082
C 12 0.157 0.127 0 19
KS 0 1.075
KS 3 1.107
K 1 102 5303 5
K 4 111 5662 5