Удалить почти повторяющиеся строки

Оказывается, проблема связана со звуковой картой CA0132 и ее неспособностью обмениваться данными с машинами Linux. Драйвера для этой звуковой карты нет, и с ~2013 года с этой проблемой столкнулись еще с десяток человек. Извините, что разочаровал. Я ответил только для того, чтобы вы не теряли время на эту бесконечную проблему. Будем надеяться, что в ближайшем будущем Creative собирается выпустить Linux-драйвер для звуковой карты.

4
06.05.2016, 15:41
3 ответа

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

$ sed '$!N; /\(.*\)\n\1:FOO/D; P;D' file
red.7
green.2:FOO
blue.6
yellow.9:FOO

Объяснение:

  • $!N - если мы еще не на последней строке, добавляем следующую строку к пробелу шаблона, разделенному новой строкой
  • /\(.*\)\n - сопоставляем все до новой строки (т.е. первая из каждой пары строк) и сохранить в группу захвата
  • \1:FOO теперь соответствует всему, что было захвачено из первой строки, а затем :FOO (\1 является обратной ссылкой на первую группу захвата)
  • /\(. *\)\n\1:FOO/D - если вторая строка каждой пары такая же, как и первая, за которой следует :FOO, то Dудалите первую
  • Print и Dудалите оставшуюся строку, готовую начать следующий цикл

или более аккуратно (спасибо @don_crissti)

 sed '$! N; /\(.*\)\n\1:FOO/!P;D' файл'

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

4
27.01.2020, 20:46

Один из способов в awk:

awk '$0 != x ":FOO" && NR>1 {print x} {x=$0} END {print}' file

Сохраняет строку, затем проверяет в начале каждой строки, что она не содержит сохраненной строки + :FOO. Выводит последнюю строку, так как в ней не может быть :FOO, так как ее нет.

5
27.01.2020, 20:46

В простейшем случае, чтобы сохранить строки без :FOO, вы можете просто удалить :FOO и затем пройти через uniq:

$ sed 's/:FOO$//' file | uniq
red.7
green.2
blue.6
yellow.9

Если вы предпочитаете сохранить строки :FOO и предполагаете, что они всегда идут после своих собратьев без суффикса, вы можете попробовать:

$ rev file | sed 's/:/ /' | uniq -f1 | sed 's/ /:/' | rev
red.7
green.2:FOO
blue.6
yellow.9:FOO

rev печатает каждую строку справа налево. sed заменяет первый : пробелом, чтобы uniq мог использовать распознавание FOO (или OOF, в данном случае) в качестве первого поля, которое должно быть проигнорировано, следующий sed возвращает : обратно и финальный rev снова печатает слева направо.


К сожалению, несмотря на то, что утверждает документация, uniq использует в качестве разделителя полей не только пробел и табуляцию, но и практически любой неалфавитно-цифровой символ:

$ printf 'foo/1\nfoo/2\nfoo%%3\nfoo:4\n' 
foo/1
foo/2
foo%3
foo:4
$ printf 'foo/1\nfoo/2\nfoo%%3\nfoo:4\n'  | uniq -f1
foo/1

Это означает, что приведенное выше решение не будет работать, если у вас есть такие символы. В качестве альтернативы вы можете grep найти все случаи :FOO в вашем файле, удалить :FOO и передать результат в новый grep как список шаблонов, которых следует избегать:

$ grep -hFxv "$(grep ':FOO' file | cut -d: -f1)" file 
red.7
green.2:FOO
blue.6
yellow.9:FOO
5
27.01.2020, 20:46

Теги

Похожие вопросы