perl -lane '
BEGIN {
print $H = join "|", map { s/.*/[$&]/r } @H = qw/user module action doAjax ajaxAction/;
pos($H) = 0;
push(@pos, pos($H)-$p), $p=pos($H) while $H =~ /\[/g;
$fmt = join "", map { "\%-${_}s" } @pos[1..$#pos], length($H)-$p;
}
my(%h, %H) = $F[-1] =~ /[?&]\K([^=]+)=([^&]+)/g;
@H{@H} = ($F[-1] =~ m|^/([^/]+)|, @h{qw/m a doajax action/});
print sprintf $fmt, map { $H{$_} // "null" } @H;
' logfile
[user]|[module]|[action]|[doAjax]|[ajaxAction]
userx contacts form null null
usery customer null request getContacts
userx meeting null date null
Опции Perl:
-l
делает ORS = RS = \n
-a
сохраняет поля в массив @F
, полученный путем разделения текущей записи на /\s+/
, например, $F[0] => $1, $F[1] => $2, ..., $F[-1] => $NF
-n
устанавливает неявный цикл, который считывает входной файл построчно и не выводит, если его не запрашивают.
Блок BEGIN:
Сначала мы печатаем заголовок. Затем мы определяем формат динамически на основе заголовка. Для каждой прочитанной строки мы устанавливаем хэш %h, ключами которого являются строки до =, а значениями — строки после =. Строка, на которую нужно смотреть, примыкает к ? или & слева и & справа. Затем мы настраиваем другой хэш %H, чьи ключи переименованы в версии хэша %h. Затем мы печатаем хеш на основе формата, который мы вычислили в блоке BEGIN.