Как использовать awk для нескольких файлов? - PullRequest
0 голосов
/ 07 октября 2019

Я использую Linux. Я написал код, который выглядит следующим образом:

for x in {10..20}:{00..59}; do awk -F';' '/'"$x"'/ {y+=$7} END {print y}' Data26092019; done

Как использовать эту команду для нескольких файлов, например: Data26092019 и Data27092019?

Файлы выглядят так:

09:55:13;ACSEL;4.850;16;77.60;1;1
09:55:13;ACSEL;4.850;40;194.00;2;1
09:55:13;ACSEL;4.850;465;2255.25;3;1
...

Пример вывода:

Data26092019 4988 10:00
Data26092019 2778 10:01
...
Data27092019 3252 10:00
Data27092019 3002 10:01

Возможно, он должен работать с другим циклом for или вы можете указать файлы.

Основная команда:

for x in {10..20}:{00..59}; do awk -F';' '/'"$x"'/ {y+=$7} END {print y}' Data26092019; done

Он должен быть выполнен на Data26092019 и Data27092019.

Ответы [ 5 ]

1 голос
/ 07 октября 2019

Проще говоря, вы должны сделать следующее:

for file in f1 f2 f3 f4; do
   for time in {10..20}:{00..59}; do 
      sum=$(awk -v t="${time}" -F";" '($0~"^"t){sum+=$7}END{print sum}' "$file"
      echo "$file $sum $time"
   done
done

Это, однако, очень медленно, так как вы будете открывать каждый файл несколько раз при поиске определенного временного ключа.

Я считаю, что вы после этого:

awk 'function print_summary(    h,m,key) {
        for (h=10;h<=20;++h) {
           for (m=0;m<60;++m) {
              key=sprintf("%0.2d:%0.2d",h,m)
              print fname, sum[key]+0, key
           }
        }
     }
     BEGIN{FS=";"}
     (FNR==1){if(NR>1) print_summary(); delete sum; fname=FILENAME}
     !/^..:..:../{next}
     { key=substr($0,1,5) }
     { sum[key]+=$7 }
     END { print_summary() }' file1 file2 file3 ...

Этот метод пропустит пустые файлы, но сообщит именно то, что ожидается.

1 голос
/ 07 октября 2019

РЕДАКТИРОВАТЬ: В случае, если вы хотите использовать END (или у вас нет GNU awk) +, вы хотите иметь сумму в том же порядке, в котором вы находитесьпередавая Input_files, попробуйте следующее.

Использование END:

awk '
BEGIN{
 FS=";"
}
!filename[FILENAME]++{
  a[++count]=FILENAME
}
{
  sum[FILENAME]+=$7
}
END{
  for(i=1;i<=count;i++){
    print "Sum of minute for file: " a[i] " is: " sum[a[i]]
  }
}'  Data26092019 Data27092019


Использование ENDFILE:

Не могли бы вы попробовать следующее, не тестировалось, так как нет образцов, предоставленных OP. Требуется GNU awk.

awk 'BEGIN{FS=";"} {sum+=$7} ENDFILE{print "Sum of minute for file: " FILENAME " is: " sum;sum=""}' Data26092019 Data27092019
0 голосов
/ 07 октября 2019

Большое спасибо за все добрые ответы. Я новичок, я не могу понять и прокомментировать все разные решения. Что мне больше всего помогло, так это функциональное решение от @kvantour. Код:

awk 'function print_summary(    h,m,key) {
        for (h=10;h<=20;++h) {
           for (m=0;m<60;++m) {
              key=sprintf("%0.2d:%0.2d",h,m)
              print fname, sum[key]+0, key
           }
        }
     }
     BEGIN{FS=";"}
     (FNR==1){if(NR>1) print_summary(); delete sum; fname=FILENAME}
     !/^..:..:../{next}
     { key=substr($0,1,5) }
     { sum[key]+=$7 }
     END { print_summary() }' file1 file2 file3 ...
0 голосов
/ 07 октября 2019

Используя gawk, вы можете адаптировать ответ @JamesBrown:

gawk -F\; '{
    sum += $7
} 
ENDFILE {
    print FILENAME, sum
    sum=0
}' file1 file2
0 голосов
/ 07 октября 2019

Другое:

$ awk -F\; '{
    sum[FILENAME]+=$7
} 
END {
    for(f in sum)
        print f,sum[f]
}' file1 file2

Вывод с 2 копиями ваших образцов данных:

file1 3
file2 3
...