Intereting Posts
Как определить DNS-сервер в openvpn? Попытки унифицировать Linux и другие бесплатные Unix? Как разрешить модуль радиуса pam в centos для пароля пользователя, а также один пароль времени Скомпилированный исполняемый файл ChrUbuntu (Acer): Как загрузить ядро ​​3.8.0-16 вместо 3.4.0? Двоичный, не доступный из Bash, несмотря на то, что он находится в пути Как заставить бесконечно исполняющуюся команду убивать себя, когда выполняются определенные условия? Блокировать движение для любого типа скобок? Передавать аргументы команде, запущенной другим пользователем Как я могу вывести «временно» в оболочку, как это делает завершение вкладки zsh? Спящий ключ перестает работать через некоторое время подсчитать все конкретные слова, которые заканчиваются в каждой строке Как установить .bin-файл, который дает ошибку, что ему нужно больше места в / tmp? apt-get update не работает при дебианском сжатии с "File not found" Как использовать dpkg -i для установки пакета и зависимостей, где все зависимости находятся в одной папке

Скрипт оболочки для сортировки по столбцу даты с помощью команды Linux ‘sort’

У меня есть файл с именем session.log Он содержит некоторые текстовые данные. 1-й столбец содержит серийный номер. 2-й столбец содержит имя пользователя. 3-й столбец содержит дату последнего входа. 4-й столбец содержит результат.

Один пользователь вошел в систему несколько раз. Мне нужно найти дату последнего входа в систему для каждого уникального пользователя. Поэтому я написал сценарий оболочки. Выходные данные будут отображать строки с последней датой входа (3-й столбец) для каждого уникального пользователя (2-й столбец). Вывод не должен содержать одно и то же имя пользователя несколько раз.

 $ cat session.log 
 1 u1 2018-05-19 проход
 2 u2 2018-06-15 проход
 3 u3 2018-05-18 проход
 4 u4 2018-05-17 проход
 5 u2 2018-05-14 проход
 6 u4 2018-07-11 проход
 7 u1 2018-05-16 проход
 8 u3 2018-05-13 проход
 9 u1 2018-08-12 проход
 10 u1 2018-05-10 проход

Что я пробовал:

( awk {print} session.log | cut -f2 -d' ' | sort | uniq ) > store.txt for line in $(cat "store.txt") do touch "$line.txt" grep "$line" session.log > "$line.txt" temp=$(sort -k3 "$line.txt" | awk 'END{print}') echo $temp > "$line.txt" cat "$line.txt" done 

Выход

 $ ./sort.sh
 9 u1 2018-08-12 проход
 2 u2 2018-06-15 проход
 3 u3 2018-05-18 проход
 6 u4 2018-07-11 проход

Сценарий оболочки работает для формата даты (гггг-мм-дд) и (гггг / мм / дд). Есть ли лучший код для выполнения той же работы? Используя awk как мы это делаем?

РЕДАКТИРОВАТЬ:

 $ cat sort.sh ( awk {print} session.log | cut -f2 -d' ' | sort | uniq ) > store.txt for line in $(cat "store.txt") do #touch "$line.txt" grep "$line" session.log > "$line.txt" echo $(sort -k3 "$line.txt" | awk 'END{print}') #temp=$(sort -k3 "$line.txt" | awk 'END{print}') #echo $temp > "$line.txt" #cat "$line.txt" done rm -f store.txt 

 $ sort -k 3,3r session.log | awk '!seen[$2]++ { print }' 9 u1 2018-08-12 pass 6 u4 2018-07-11 pass 2 u2 2018-06-15 pass 3 u3 2018-05-18 pass 

( { print } может быть удален полностью, я только включаю его, чтобы показать, что происходит. Действие по умолчанию – распечатать всю входную запись, если условие выполнено.)

Это сортирует файл, который у вас есть, по убыванию дат (сначала самая последняя дата). Программа awk считывает отсортированные данные и распечатывает первую найденную запись для каждого пользователя. seen переменная – это ассоциативный массив / хеш, который использует имена пользователей в качестве ключей. Если его значение равно нулю для пользователя, то этого пользователя еще не видели, и поэтому печатается строка из файла.


Ваш код с моими аннотациями:

 # get list of unique usernames from log: ( awk {print} session.log | cut -f2 -d' ' | sort | uniq ) > store.txt # shorter equivalent: # cut -d ' ' -f2 store.txt # loop over the usernames: for line in $(cat "store.txt") do # get entries related to this user: grep "$line" session.log > "$line.txt" # echo the last entry: echo $(sort -k3 "$line.txt" | awk 'END{print}') # shorter equivalent of both of the above commands: # awk -v user="$line" '$2 == user { print }' session.log | sort -k3,3 | tail -n 1 done rm -f store.txt 

Итак, альтернативный подход, основанный на вашем цикле оболочки:

 cut -d ' ' -f2  

Опять же, { print } может быть исключен из сценария awk выше.

Это по-прежнему сортирует подмножества журнала сеанса один раз для каждого пользователя, что отчасти расточительно.

Предварительная сортировка журнала по убыванию дат:

 sort -k3,3r -o sorted.log session.log cut -d ' ' -f2  

Это по-прежнему требует от нас сканировать журнал сверху для каждого пользователя. Естественное улучшение - позволить awk отслеживать, каких пользователей видели, а каких не видели, что дает вам мой ответ в самом верху.