Удалить дубликаты в каждой строке файла
Как я могу удалить дубликаты в каждой строке, например, здесь?
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 ответа
Вот вариант с использованием awk:
awk '{ while(++i<=NF) printf (!a[$i]++) ? $i FS : ""; i=split("",a); print ""}' infile > outfile
Редактировать Обновлено с комментариями:
while (++i<=NF)
Инициализирует цикл while, предваряя "i", поскольку $0 - это полная строка в awk.
Таким образом, он начинается с $1 (первое поле). Переходит по линии до конца (меньше или равно "NF", которое встроено в awk для "Количество полей"). Разделителем полей по умолчанию является пробел, вы можете легко изменить разделитель по умолчанию.
printf (!a[$i]++) ? $i FS : ""
Это троичная операция.
Итак, если вход не находится в массиве
!a[$i]++
, затем он печатает $i, если это так, он печатает "". (Вы можете удалить!
и повернуть вспять$i FS : ""
если тебе не нравится это так).i=split("",a)
Обычно это нулевое разделение. В этом случае он сбрасывает I для следующей строки.
print ""
заканчивает строку для вывода (не 100%, почему, на самом деле), в противном случае вы бы получили вывод:
1 2 3 5 4 1 2 3
вместо1 2 3
5 4 1 2 3
Поскольку ruby
поставляется с любым дистрибутивом Linux, о котором я знаю:
ruby -e 'STDIN.readlines.each { |l| l.split(" ").uniq.each { |e| print "#{e} " }; print "\n" }' < test
Вот, test
это файл, который содержит элементы.
Чтобы объяснить, что делает эта команда - хотя Ruby почти читается слева направо:
- Прочитайте ввод (который исходит от
< test
через вашу раковину) - Пройдите каждую строку ввода
- Разбить строку на основе одного пробела, разделяющего элементы, в массив (
split(" ")
) - Получить уникальные элементы из этого массива (по порядку)
- Для каждого уникального элемента выведите его, включая пробел (
print "#{e} "
) - Напечатайте новую строку, как только мы закончим с уникальными элементами
Не чистый баш, но...
while read line; do
printf "%s\n" $line | sort -u | tr '\n' ' '
echo ''
done < file
Линии будут отсортированы как побочный продукт.