У меня есть список из одного столбца, содержащий ~ 100 строк, в котором некоторые строки повторяются, и моя цель - избавиться отспецифическийдублировать строки и оставить толькоодинскопируйте, а остальные строки оставьте нетронутыми.
Выдержка из файлов, над которыми я работаю:
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
C(Mn9)
C(Mn6)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
Моя цель — удалить все повторяющиеся строки, содержащие C(Xx0-9), и оставить одну из них, сохранив V(Xxx..).
Результат, к которому я стремлюсь:
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(C1)
C(C4)
C(Mn9)
C(Mn6)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
Я использовал команду:
sed '0,/C(Mn9)/{/C(Mn9)/d}' inputfile.txt | sed '0,/C(Mn6)/{/C(Mn6)/d}'
и это работает, но этого недостаточно для всего файла, потому что там много C(Xx1-50), я думал использовать регулярное выражение, но я не знаю как, поэтому мне нужна ваша помощь.
решение1
$ awk '!(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
Вышеуказанное предполагает, что у вас нет пробелов до/после видимых символов в вашем примере ввода. Если они есть, то удалите их, например:
$ awk '{gsub(/^[[:space:]]+|[[:space:]]+$/,"")} !(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
решение2
Предлагаю использовать sed
для сбора строк в пространстве ожидания, чтобы проверить, появлялись ли они ранее:
sed -n 'H;G;/^\(C([^)]*)\).*\1 *\n/!P'
H
добавляет текущую строку в отведенное для нее местоG
добавляет пространство удержания со всеми линиями, которые мы когда-либо видели, к пространству шаблонаC([^)]*)
является одним из такихC(…)
шаблонов,^
привязывает его к началу строки и окружает\(…\)
, поэтому на него можно ссылаться как на\1
later. Нам нужен\1 *\n
шаблон as с новой строкой (после возможных пробелов), чтобы избежать сопоставления с только что добавленной строкой в конце. Таким образом, весь шаблон/^\(C([^)]*)\).*\1 *\n/
соответствует строке с дубликатомC(…)
, поэтому только если это!
не совпадает,P
вывести все до первой новой строки (= без добавленного пробела), в то время как вывод по умолчанию подавляется-n
опцией
Обратите внимание, что в зависимости от sed
версии и размера файла это может привести к сбою, поскольку со временем все строки окажутся в памяти.