#linux #shell #text #command-line #archlinux
#linux #оболочка #текст #командная строка #archlinux ( архлинукс )
Вопрос:
У меня есть такой файл, как этот
2/2
2/2
2/2
3/3
1/1
1/1
2/2
1/1
3/3
и т.д..
Я хочу удалить все дубликаты отдельных номеров и подсчитать, сколько их в каждом номере, но сохранить их первоначальный порядок следующим образом
4 2/2
2 3/3
3 1/1
Я попытался
sort myfile.txt | uniq -c
но это возвращает вывод, подобный этому, и не сохраняет его в порядке первого экземпляра в файле
2 3/3
4 2/2
3 1/1
Я также попробовал просто uniq -c сам по себе, но это не устраняет все дубликаты. Я использую Arch Linux на самом последнем ядре, поэтому мне нужны команды для этого.
Извините, что это было так запутанно, но любая помощь была бы признательна 🙂
Ответ №1:
Что-то вроде этого будет работать:
awk '
# This first line simply ensures that `order` is an array
BEGIN {delete order[0]}
! ($1 in seen) {order[length(order) 1] = $1}
{seen[$1] }
END {for (i in order) print seen[order[i]], order[i]}
' data.txt
В этом скрипте мы поддерживаем два ассоциированных массива («словари» или «хэши» на других языках).:
order
записывает порядок, в котором мы встречаем новые значения, иseen
записывает, сколько раз мы видели определенное значение
После обработки данных мы выполняем итерацию order
, чтобы получить значения в том порядке, в котором они появились, и ищем их количество в seen
массиве.
Учитывая ваш пример ввода, это приводит к:
4 2/2
2 3/3
3 1/1
Комментарии:
1. Альтернативная реализация:
!seen[$1] {order[n ] = $1}
затем в КОНЕЧНОМ блокеfor (i=0; i<n; i ) ...
— цикл сfor (i in a)
, я полагаю, не гарантирует порядок индексов.
Ответ №2:
Используйте этот однострочный Perl:
perl -lne 'push @order, $_ if !$seen{$_} ; END { print "$seen{$_} $_" for @order; }' in_file
Однострочник Perl использует эти флаги командной строки:
-e
: Указывает Perl искать код в строке, а не в файле.
-n
: Перебирайте ввод по одной строке за раз, присваивая ему значение $_
по умолчанию.
-l
: Удалите разделитель строк ввода ( "n"
по * NIX по умолчанию) перед выполнением кода в строке и добавьте его при печати.
Массив @order
сохраняет входные строки в порядке ввода, только первое вхождение каждой строки (благодаря if !$seen{$_}
условию). Хэш %seen
содержит уникальные входные строки в качестве ключей и количество вхождений в качестве значений.
END { ... }
Блок печатает содержимое хэша %seen
в порядке, указанном во входных данных (благодаря @order
).
СМОТРИТЕ ТАКЖЕ:
perldoc perlrun
: как выполнить интерпретатор Perl: переключатели командной строки