2

У меня есть список символов, таких как ...

wer
sfe
efo

Как удалить все экземпляры этих (уникальных) символов из другого списка (неуникальных) символов?

Таким образом, в следующем списке строки, начинающиеся с wer , будут удалены дважды, а sfe один раз:

wer-alskjdfi
efr-4siosejf
rte-alskjdfs
wer-alskjsef
sfe-ooskjdfi

Все остальные строки должны быть не тронуты, оставляя символ и символы после "-":

efr-4siosejf
rte-alskjdfs

Мне нужно сделать это, используя sed/awk/grep/bash или другие инструменты командной строки. Я знаю, как написать команду sed для поиска и удаления по одному значению за раз, но как мне сделать это для 100k+ значений?

4 ответа4

2

Предполагая, что ваши списки находятся в файлах

awk -F- 'NR==FNR {exclude[$1]++; next} !($1 in exclude)' list_of_symbols filename

grep также вариант

grep -v -f <(sed 's/^/^/' list_of_symbols) filename

Бит sed добавляет якорь регулярного выражения в начало каждой строки.

1

Вам нужно сохранить порядок вашего второго файла?  Можете ли вы указать максимальное количество повторений строки?  Если ответы на оба вопроса «нет», я предложил бы comm

sort file1 file1 > file1.sorted     sort file2 > file2.sorted
-------------------------------     -------------------------
efo                                 efr
efo                                 rte
sfe                                 sfe
sfe                                 wer
wer                                 wer
wer

comm -13 file1.sorted file2.sorted
efr
rte

Включите достаточное количество копий file1 в file1.sorted чтобы охватить максимальное количество вхождений любой строки в file2 .

1

Что если в файле 2 есть символы после каждого из этих символов?  Я хочу сделать то же самое, но сохранить за собой символы.

Хорошо, сделайте копию file2 котором есть только поле, по которому вы хотите выполнить фильтрацию.  И, если текущий file2 имеет «неуникальный символ», за которым сразу же следуют «завершающие символы» (например, efr-42 , rte-17 и т.д.), Сделайте еще одну копию file2 где они разделены пробелом.  Вот примеры команд на основе предоставленных вами данных примера:

sed 's/\(...\).*/\1/'        file2.sorted > file2.symbol_only
sed 's/\(...\)\(.*\)/\1 \2/' file2.sorted > file2.separated

или же

sed 's/\([^-]*\)-.*/\1/'        file2.sorted > file2.symbol_only
sed 's/\([^-]*\)\(-.*\)/\1 \2/' file2.sorted > file2.separated

… На основе новых данных, которые вы добавили в свой вопрос.  Затем используйте comm как раньше:

comm -13 file1.sorted file2.symbol_only > file2.no_match

... и соедините символы с последними символами:

join file2.no_match file2.separated

При необходимости используйте другой sed для удаления добавленных вами пробелов.


Мне пришло в голову, что вы могли бы использовать этот трюк, чтобы вернуть выходной файл в исходный порядок file2 .

  1. Создайте копию исходного file2 с номерами строк.
  2. Перемешайте номера строк справа от символов.
  3. (выше, начиная с команд sort )
  4. Сортировать вывод по исходному номеру строки.
  5. Вычеркните номера строк.

Дайте мне знать, если вам нужна помощь с этим.

0

Не зная ничего о SED и т.д., Основной дизайн в моем личном псевдокоде:

сортировать список строк, которые будут удалены (Список A)

сортировать список строк, который содержит элементы, которые должны быть удалены (Список B)

Для каждого элемента в списке A

Repeat until Item (List B) > Item (List A)
    if the Item (List B) equals Item (List A) 
        remove item (List B)
    next Item (List B)
Next Item (List A)

Примечание: "Удаление" элемента может быть проблематичным - лучше заменить эту строку на одну, добавив элемент к новой

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