Удалить строку из файла с именем в другом

У меня есть следующий список:

NM_000014 3
NM_000015 0
NM_000016 0
NM_000017 0
NM_000018 0
NM_000019 28
NM_000020 0
NM_000021 0
NM_000022 0
NM_000023 0
NM_000024 8
NM_000025 0
NM_000026 0

И у меня есть еще один файл только с первым столбцом:

NM_000031
NM_000032
NM_000033
NM_000034
NM_000022
NM_000035
NM_000036
NM_000037
NM_000023
NM_000038
NM_000039
NM_000040
NM_000041
NM_000042

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

NM_000014 3
NM_000015 0
NM_000016 0
NM_000017 0
NM_000018 0
NM_000019 28
NM_000020 0
NM_000021 0
NM_000024 8
NM_000025 0
NM_000026 0

(удаление NM_000022 и NM_00023 с соответствующими значениями)

Спасибо!!

3 ответа

Решение

С awk:

awk 'NR==FNR {a[$0]; next}; {if ($1 in a) next}; 1' f1.txt f2.txt

Введите файл с одним столбцом в качестве первого аргумента, а тот, который проверяет членство (первый столбец) в качестве второго аргумента.

  • NR==FNR {a[$0]; next}, Вот NR==FNR будет верно только для первого файла, тогда мы сохраняем каждую строку в массив a так что мы можем выполнить тест членства для первого аргумента второго файла, затем мы перейдем к следующей строке без каких-либо дальнейших операций со вторым файлом

  • {if ($1 in a) next}; 1 будет выполняться только для второго файла, который нужно проверить, здесь мы проверяем, находится ли первый аргумент, разделенный пробелами, в массиве a, если присутствует, то переходя к следующей строке, иначе печатая всю строку.

Пример:

$ cat f1.txt 
NM_000031
NM_000032
NM_000033
NM_000034
NM_000022
NM_000035
NM_000036
NM_000037
NM_000023
NM_000038
NM_000039
NM_000040
NM_000041
NM_000042

$ cat f2.txt 
NM_000014 3
NM_000015 0
NM_000016 0
NM_000017 0
NM_000018 0
NM_000019 28
NM_000020 0
NM_000021 0
NM_000022 0
NM_000023 0
NM_000024 8
NM_000025 0
NM_000026 0

$ awk 'NR==FNR {a[$0]; next}; {if ($1 in a) next}; 1' f1.txt f2.txt
NM_000014 3
NM_000015 0
NM_000016 0
NM_000017 0
NM_000018 0
NM_000019 28
NM_000020 0
NM_000021 0
NM_000024 8
NM_000025 0
NM_000026 0

Вы также можете использовать sed с петлей Баша.

Эта команда изменяет file1 на месте (создание резервной копии file1.bak), удаляя каждую строку, которая начинается с любой строки из file2:

while read line ; do sed -i.bak "/$line.*/d" file1 ; done < file2

Как с командой 'grep' здесь:)

grep -Fvf oneColumnedFile listFile > outfile
Другие вопросы по тегам