Intereting Posts
Как восстановить доступ к Интернету? ТОЛЬКО программа, которая по-прежнему пользуется Интернетом – это разнообразие (приложение для обоев) Как изменить ускорение мыши в X на постоянной основе? ubuntu + как установить команду patch Сайт по-прежнему загружается с настройками по умолчанию UFW Подпроцессы bash / gnome-terminal не заканчиваются (CentOS / RHEL) Как установить команду редактора для использования * только * для редактирования командной строки в zsh? Проблемы с платформой OpenCL Получить абсолютный путь к файлу OS X Поддержка Apple Bluetooth Keyboard в Ubuntu 16.04 Как получить URL-адрес через HTTP с netcat? Отобразить текущий каталог текущей панели в статусе Открывается ли консоль после загрузки? postfix + Cyrus SASL – не удается подключиться к серверу saslauthd: нет такого файла Есть ли простой инструмент Bash, который может быстро отображать базовый HTML? Какие дистрибутивы Linux упрощают обновление?

Удалите последовательные строки в CSV с повторяющимися значениями в одном поле, но сохраните последнюю строку

У меня есть длинный файл CSV с двумя столбцами, который включает в себя прогон последовательных дубликатов:

... 1500,1533 1554,1678 1554,1703 1554,1728 1593,1766 ... 

Мне нужно удалить все эти дубликаты, кроме последнего, так что вывод для примера выше:

 ... 1500,1533 1554,1728 1593,1766 ... 

Также мне нужно сохранить остальные строки в файле в исходном порядке.

Я попробовал tac file.csv | sort -k1,1 -r -u -t, tac file.csv | sort -k1,1 -r -u -t,

но это не дало желаемого результата, а функции сортировки перепутали мой порядок строк.

С sed :

 sed '$!N;/\(.*,\).*\n\1/!P;D' infile 

N означает, что в пространстве шаблонов всегда есть две последовательные строки, а sed P – первый из них, только если первое поле в этой строке не совпадает с первым полем во второй строке. Затем D удаляет первую строку из пространства шаблонов и перезапускает цикл.


Другой способ с gnu datamash (если ваш файл отсортирован, так как datamash требует отсортированного ввода):

 datamash -t ',' -g 1 last 2 <infile 

Это g объединяет ввод с разделителями по 1 -ому полю, распечатывая только last значение (из 2 го столбца) каждой группы.


Если ваш файл не отсортирован, datamash может сортировать его через -s :

 datamash -t ',' -s -g 1 last 2 <infile 

но это означает, что начальный порядок строк не будет сохранен. Так что это может не делать то, что вы хотите. В этом случае вы можете использовать sed / awk / perl т. Д. …

И альтернативный awk:

  awk -F, 'NR==1{old=$0;check=$1}NR>1 && $1 != check {print old}{old=$0;check=$1}END{print old}' knovice 1500,1533 1554,1728 1593,1766 

Вот еще один awk подход (спасибо @Glenn ):

  tac file | awk -F, 'awk -F, '!seen[$1]++' | tac 

-F, устанавливает разделитель. В awk действие по умолчанию, когда выражение принимает значение true, это печать текущей строки. !seen[$1] будет истинным, если первое поле не существует в рассматриваемом массиве. Однако, поскольку мы также создаем его с seen[$1]++ , это будет только ложным в первый раз, когда это видно. В результате будет напечатан только первый дубликат.

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