awk group-by по подстроке столбца

У меня есть следующий файл журнала:

/veratt/po/dashboard.do 
/veratt/po/dashboardfilter.do?view=R
/veratt/po/leaseagent.do?view=R
/veratt/po/dashboardfilter.do?&=R&=E&propcode=0&display=0&rateType=0&floorplan=&=Display&format=4&action=getReport
/veratt/po/leaseagent.do
/veratt/po/leaseagent.do?view=V

Желаемый вывод AWK для счетчика каждого HTTP-запроса (за вычетом параметров запроса)**

/veratt/po/dashboard.do  - 1
/veratt/po/leaseagent.do - 3
/veratt/po//veratt/po/dashboardfilter.do  - 2

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

awk  '{a[$2]=a[$2]+1;} END {for( item in a) print item , a[item];} ' 

awk
person user3646625    schedule 05.06.2014    source источник
comment
Является ли отсутствующий ? в строке dashboardfilter.do законным или опечаткой?   -  person n0741337    schedule 06.06.2014
comment
это опечатка, извините, исправлю   -  person user3646625    schedule 06.06.2014
comment
В Awk есть += и ++ для увеличения.   -  person Kaz    schedule 06.06.2014
comment
или sed /[?].*//' logfile file2 | sort | uniq -c ? Помещает графа в начало очереди. ИХМО читать легче ;-) Удачи.   -  person shellter    schedule 06.06.2014


Ответы (2)


awk -F\? '{ count[$1]++} 
          END { for (item in count)
                  printf("%s - %d\n", item, count[item]) }' logfile
  • -F: отдельные поля по ? символу, поэтому $1 — это запрос; это параметры URL, они находятся в $2, существование которых мы игнорируем. Примечание: это можно сделать с помощью BEGIN { FS="?" }. Примечание: если FS содержит более одного символа, оно рассматривается как регулярное выражение.
  • { count[$1]++ }: для каждой строки подсчитайте количество вхождений $1.
  • END: запустить этот блок в конце обработки всех входных данных
  • for (item in count): итерация переменной item по ключам в массиве count.
  • printf("%s - %d\n", item, count[item]): форматированная печать элемента и его количества, разделенных тире с пробелами. Примечание: %d можно заменить на %s; awk слабо типизирован.
person Kaz    schedule 05.06.2014
comment
Вам нужно поставить вопросительный знак (-F'?') в кавычки — это подстановочный знак. - person glenn jackman; 06.06.2014
comment
это не обязательно :) -F"?" -F? -F'?' и BEGIN{FS="?"} равны @glennjackman - person Haifeng Zhang; 06.06.2014
comment
@haifzhan glenn считает, что в вашей файловой системе может быть файл с именем, скажем, -FA. Затем -F? соответствует имени этого файла и преобразуется в -FA. - person Kaz; 06.06.2014
comment
Спасибо, что указали на это, я неправильно понял :) извините, Гленн - person Haifeng Zhang; 06.06.2014

test.txt

/veratt/po/dashboard.do
/veratt/po/dashboardfilter.do?view=R
/veratt/po/leaseagent.do?view=R
/veratt/po/dashboardfilter.do?&=R&=E&propcode=0&display=0&rateType=0&floorplan=&=Display&format=4&action=getReport
/veratt/po/leaseagent.do
/veratt/po/leaseagent.do?view=V

команда:

awk 'BEGIN{FS="?"} {a[$1]++} END{for(i in a) print i, a[i]}' test.txt

выход:

/veratt/po/leaseagent.do 3
/veratt/po/dashboard.do 1
/veratt/po/dashboardfilter.do 2

объяснять:

BEGIN{FS="?"} установить ? быть разделителем полей, поэтому $1 будет подстрокой перед первым символом ?. Это выполняется только один раз перед обработкой содержимого test.txt.

{a[$1]++} создать массив, индекс - это подстрока, сделать его автоинкрементным.

END{for(i in a) print i, a[i]} перебирает массив, проверяет его индекс и соответствующее значение, блок END запускается один раз после обработки всех строк test.txt.

person Haifeng Zhang    schedule 05.06.2014
comment
@downvoter, сервер stackoverflow не работал пару минут, поэтому формат вставки был перепутан. - person Haifeng Zhang; 06.06.2014