Как обработать два файла результатов, используя awk? - PullRequest
3 голосов
/ 28 декабря 2011

У меня есть два файла, которые следуют одному и тому же шаблону:

TEST CASE 1:  0.004 seconds
TEST CASE 2:  0.043 seconds
TEST CASE 3:  0.234 seconds
TEST CASE 4:  0.564 seconds
....

То, что я пытаюсь сделать, - это рассчитать ускорение для каждого тестового случая, что делается путем значение из одного файла и деление его на соответствующее значение в другом файле.

Есть ли простой способ сделать это, используя awk?

Ответы [ 3 ]

3 голосов
/ 28 декабря 2011

Если они имеют одинаковые тестовые случаи, вы можете просто объединить два файла в отсортированном виде, а затем использовать awk для обработки результирующего потока, сохраняя первый раз для каждой пары и затем вычисляя во второй раз.

Что-то вроде следующего транскрипта:

pax:~$ cat file1
TEST CASE 1:  0.004 seconds
TEST CASE 2:  0.043 seconds
TEST CASE 3:  0.234 seconds
TEST CASE 4:  0.564 seconds

pax:~$ cat file2
TEST CASE 1:  0.003 seconds
TEST CASE 2:  0.040 seconds
TEST CASE 3:  0.134 seconds
TEST CASE 4:  0.664 seconds

pax:~$ ( cat file1 |sed 's/:/: A /' ; cat file2 |sed 's/:/: B /' ) |sort |awk '{
    if (state == 0) {
        before = $5;
        state = 1;
    } else {
        print before" -> "$5" ("("int(100 * $5 / before - 100)"%)")"
        state = 0;
    }
}'
0.004 -> 0.003 (-25%)
0.043 -> 0.040 (-6%)
0.234 -> 0.134 (-42%)
0.564 -> 0.664 (17%)

Вот как это работает.Подоболочка ( ... ) изменяет оба файла, поэтому они будут правильно сортироваться с помощью простой команды sort в следующее:

TEST CASE 1: A   0.004 seconds
TEST CASE 1: B   0.003 seconds
TEST CASE 2: A   0.043 seconds
TEST CASE 2: B   0.040 seconds
TEST CASE 3: A   0.234 seconds
TEST CASE 3: B   0.134 seconds
TEST CASE 4: A   0.564 seconds
TEST CASE 4: B   0.664 seconds

Другими словами, в пары значений до и после.awk имеет миниатюрный автомат с двумя состояниями.В нулевом состоянии он просто сохраняет время до и устанавливает состояние равным единице.В первом состоянии он вычисляет и печатает требуемые значения, прежде чем вернуть состояние в ноль.


Если вы хотите, чтобы номер тестового набора был включен, и естественную сортировку можно использовать (после добавления тестового примера 10 квходные файлы):

pax:~$ ( cat file1 |sed 's/:/: A /' ; cat file2 |sed 's/:/: B /' ) |sort |awk '{
    if (s == 0) {
        s = 1;
        before = $5;
    } else {
        s = 0;
        printf "%5s %s->%s (%d%%)\n", $3, before, $5, int(100 * $5 / before - 100)
    }
}' |sort -n

   1: 0.004->0.003 (-25%)
   2: 0.043->0.040 (-6%)
   3: 0.234->0.134 (-42%)
   4: 0.564->0.664 (17%)
  10: 0.564->0.764 (35%)
1 голос
/ 28 декабря 2011

Мне удалось придумать собственное решение, используя paste для объединения двух файлов результатов. Затем сценарий awk стал действительно простым, и контрольные примеры отсортированы правильно.

paste <(grep "^TEST CASE" file1) <(grep "^TEST CASE" file2) |
awk '{print "TEST CASE " $3 "  " $4 / $9}'

grep есть для получения ожидаемого ввода в paste, поскольку строки взяты из файла, который содержит много другой информации, которая мне не нужна. Если ожидаемый результат уже доступен в отдельном файле (как я уже говорил в вопросе), тогда команда становится

paste file1 file2 | awk '{print "TEST CASE " $3 "  " $4 / $9}'

Это дает в качестве вывода:

TEST CASE 1:  1.0423
TEST CASE 2:  2.34023
TEST CASE 3:  3.2423
TEST CASE 4:  4.3425
....
0 голосов
/ 28 декабря 2011

Это не совсем то, что вы просили, но пока кто-то не предоставит решение с помощью awk, вы застряли со мной, и я знаю только perl:)

#!/usr/bin/perl

use strict;
use warnings;

my $zaehler = 0;

while (<>) {
  /:\s*([\d.]*) s/;
  print(($zaehler/$1)."\n");
  $zaehler = $1;
}

Вы просто даете файл какаргумент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...