Вы хотите применить регулярное выражение только к первому полю и собрать значения для каждого пользователя в памяти в формате, подходящем для печати.
Обратите внимание, что список имеет фиксированную ширину;поэтому имя и аргументы программы находятся в поле, которое начинается в столбце 55. Аналогично, отметка времени находится в столбцах 28-32.
awk 'NR > 1 && $1 ~ /^[a-z]{3}[0-9]{3}$/ {
when = substr($0, 28, 5)
command = substr($0, 55)
if ($1 in user) {
# Append this command to previous value
user[$1] = user[$1] ORS " " command
} else {
# Create a new item in this associative array
user[$1] = " " command
}
if (NR==2 || when > max) { max=when; maxcmd = $0 }
if (NR==2 || when < min) { min=when; mincmd = $0 }
}
END {
# XXX TODO: sort array?
for (u in user) printf "User %s:\n%s\n", u, user[u]
print "Earliest start time"; print mincmd
print "Lastest start time"; print maxcmd
}' filename
Поэтому, когда мы впервые видим конкретного пользователя, они не будутбыть в users
, и поэтому мы просто помещаем их первую команду с отступом в четыре пробела в качестве значения для этого ключа в ассоциативном массиве.Если мы увидим их снова, мы добавим еще одну строку к значению, с новой строкой (ORS
) и четырьмя пробелами впереди.
NR
- номер текущей строки - мы пропускаем NR==1
, чтобыизбегайте захвата строки заголовка, и с помощью NR==2
мы знаем, что это первая строка, которую мы обрабатываем, поэтому мы устанавливаем max
и min
в их базовые значения.
В идеале, вы также должны нормализоватьвременные метки в канонической форме, так что вы можете отсортировать «вчера 21:24» до «21:23», но я не пойду туда с этим простым ответом.Вы, вероятно, хотите добавить украшения и в других местах.(Или, может быть, вы можете полагаться на тот факт, что входные данные сортируются по времени начала процесса?)
Если вы хотите, чтобы имена пользователей сортировались, в GNU Awk встроена сортировка массива;для других Awks вам нужно написать собственную простую функцию сортировки или использовать внешний конвейер.