7

Как я могу удалить дубликаты в каждой строке, например, здесь?

1 1 1 2 1 2 3
5 5 4 1 2 3 3

Я хотел бы получить этот вывод:

1 2 3 
5 4 1 2 3

Есть много строк (100 000), и в каждой строке я хочу уникальные значения. Perl может быть самым быстрым, но как я могу сделать это в Perl или Bash?

3 ответа3

12

Вот вариант с использованием awk:

awk '{ while(++i<=NF) printf (!a[$i]++) ? $i FS : ""; i=split("",a); print ""}' infile > outfile

Редактировать Обновлено с комментариями:

  1. while (++i<=NF)

    Инициализирует цикл while, предваряя "i", поскольку $ 0 - это полная строка в awk.

    Таким образом, он начинается с $ 1 (первое поле). Проходит по линии до конца (меньше или равно "NF", которое встроено в awk для "Количество полей"). Разделителем по умолчанию является пробел, вы можете легко изменить разделитель по умолчанию.

  2. printf (!a[$i]++) ? $i FS : ""

    Это троичная операция.

    Итак, если входных данных нет в массиве !a[$i]++ , тогда он печатает $ i, если это так, он печатает "". (Вы можете удалить ! и поменяйте местами $i FS : "" если вам это не нравится).

  3. i=split("",a)

    Обычно это нулевое разделение. В этом случае он сбрасывает I для следующей строки.

  4. print ""

    заканчивает строку для вывода (не 100%, почему, на самом деле), в противном случае вы бы получили вывод:

    1 2 3 5 4 1 2 3 вместо
    1 2 3
    5 4 1 2 3

5

Поскольку ruby поставляется с любым дистрибутивом Linux, о котором я знаю:

ruby -e 'STDIN.readlines.each { |l| l.split(" ").uniq.each { |e| print "#{e} " }; print "\n" }' < test

Здесь test - это файл, который содержит элементы.

Чтобы объяснить, что делает эта команда - хотя Ruby почти читается слева направо:

  • Прочитайте ввод (который идет от < test через вашу оболочку)
  • Пройдите каждую строку ввода
  • Разбить строку на основе одного пробела, разделяющего элементы, на массив (split(" "))
  • Получить уникальные элементы из этого массива (по порядку)
  • Для каждого уникального элемента выведите его, включая пробел (print "#{e} ")
  • Напечатайте новую строку, как только мы закончим с уникальными элементами
2

Не чистый баш, но ...

while read line; do
    printf "%s\n" $line | sort -u | tr '\n' ' '
    echo ''
done < file

Линии будут отсортированы как побочный продукт.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .