Как использовать grep и sed одновременно с использованием pipe - PullRequest
0 голосов
/ 23 января 2020

У меня есть 2 файла

Файл 1

TRINITY_DN10039_c1_g1_i1        216     Brassica rapa   
TRINITY_DN10270_c0_g1_i1        233     Pan paniscus  
TRINITY_DN10323_c0_g1_i2        209     Corynebacterium aurimucosum ATCC 700975  
.  
.   
TRINITY_DN10462_c0_g1_i1        257     Helwingia himalaica    
TRINITY_DN10596_c0_g1_i1        205     Homo sapiens   
TRINITY_DN10673_c0_g2_i2        323     Anaerococcus prevotii DSM 20548

Файл 2

TRINITY_DN9856_c0_g1_i1 len=467 path=[0:0-466]
GATGCGGGCCAATATGAATGTGAGATTACTAATGAATTGGGGACTAAAAA
TRINITY_DN9842_c0_g1_i1 len=208 path=[0:0-207]
AAGTAATTTTATATCACTTGTTACATCGCAATTCGTGAGTTAAACTTAAT
.
.
TRINITY_DN9897_c0_g1_i1 len=407 path=[0:0-406]
AACTTTATTAACTTGTTGTACATATTTATTAATGCAAATACATATAGAG  
TRINITY_DN9803_c0_g1_i1 len=795 path=[0:0-794]
AACTAAGACAAACTTCGCGGAGCAGTTAGAAAATATTACAAGAGATTTG

Я хочу удалить 2 строки (ту же строку и следующую строку) в файле2 чей образец совпадает со словами первого столбца 1-го файла

awk '{print $1}' file1 | sed '/here_i_want_to_insert_output_of_pipe/{N;d;}' file2

Ответы [ 3 ]

1 голос
/ 23 января 2020

Если в первом поле нет специальных символов, таких как . или / или [ или ( или \ или каких-либо специальных символов регулярных выражений, ваша идея на самом деле не так уж и плоха:

sed "$(cut -d' ' -f1 file1 | sed 's@.*@/&/{N;d}@')" file2
  • cut -d' ' -f1 file1 - извлечь первое поле из файла1
  • | sed
    • .* - заменить что-либо. ie. первое поле из файла1
    • /&/{N;d} - & заменяет все, что мы заменяем. Итак, для первого поля. Таким образом, он становится /<first field>/{N;d}
  • , затем оберните его вокруг sed "<here>" file2

Не так много известной функции, вы можете использовать другой символ для /regex/ с синтаксис \<char>regex<char> как \!regex!. Ниже я использую ~:

 sed "$(cut -d' ' -f1 file1 | sed 's@.*@\\~&~{N;d}@')" file2

Если у вас, однако, есть какие-либо специальные символы в первом поле, тогда, если вам не нужна сортировка: вы можете заменить две строки в file2 для одной строки с некоторым разделителем magi c (я выбрал ! ниже), затем сортируйте его и сортируйте file1, а затем просто join их. -v2 заставляет join выводить неисправимые строки из второго файла - ie. несоответствующие линии. После этого восстановите новую строку, заменив разделитель magi c ! на новую строку:

join -v2 <(cut -d' ' -f1 file1 | sort) <(sed 'N;s/\n/!/' file2 | sort -k1) |
tr '!' '\n'

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

join -11 -22 -v2 <(cut -d' ' -f1 file1 | sort) <(sed 'N;s/\n/!/' file2 | nl -w1 | sort -k2) |
sort -k2 | cut -d' ' -f1,3- | tr '!' '\n'

Проверено на repl

1 голос
/ 23 января 2020

Я бы сделал что-то подобное с одним awk, если только file1 не очень большой:

awk 'NR==FNR{a[$1]++; next}counter{counter--}$1 in a{counter=2}!counter' <file1> <file2>

Ввод:

file1

TRINITY_DN10039_c1_g1_i1        216     Brassica rapa   
TRINITY_DN10270_c0_g1_i1        233     Pan paniscus  
TRINITY_DN10323_c0_g1_i2        209     Corynebacterium aurimucosum ATCC 700975  
hello
TRINITY_DN10462_c0_g1_i1        257     Helwingia himalaica    
TRINITY_DN10596_c0_g1_i1        205     Homo sapiens   
TRINITY_DN10673_c0_g2_i2        323     Anaerococcus prevotii DSM 20548

file2:

TRINITY_DN9856_c0_g1_i1 len=467 path=[0:0-466]
GATGCGGGCCAATATGAATGTGAGATTACTAATGAATTGGGGACTAAAAA
TRINITY_DN9842_c0_g1_i1 len=208 path=[0:0-207]
AAGTAATTTTATATCACTTGTTACATCGCAATTCGTGAGTTAAACTTAAT
TRINITY_DN9897_c0_g1_i1 len=407 path=[0:0-406]
AACTTTATTAACTTGTTGTACATATTTATTAATGCAAATACATATAGAG  
hello
world
TRINITY_DN9803_c0_g1_i1 len=795 path=[0:0-794]
AACTAAGACAAACTTCGCGGAGCAGTTAGAAAATATTACAAGAGATTTG

Выход:

TRINITY_DN9856_c0_g1_i1 len=467 path=[0:0-466]
GATGCGGGCCAATATGAATGTGAGATTACTAATGAATTGGGGACTAAAAA
TRINITY_DN9842_c0_g1_i1 len=208 path=[0:0-207]
AAGTAATTTTATATCACTTGTTACATCGCAATTCGTGAGTTAAACTTAAT
TRINITY_DN9897_c0_g1_i1 len=407 path=[0:0-406]
AACTTTATTAACTTGTTGTACATATTTATTAATGCAAATACATATAGAG  
TRINITY_DN9803_c0_g1_i1 len=795 path=[0:0-794]
AACTAAGACAAACTTCGCGGAGCAGTTAGAAAATATTACAAGAGATTTG
0 голосов
/ 23 января 2020

Я бы сделал это с подстановкой процесса следующим образом:

while read -r -d '' line; do
    sed -i "/^${line}/{N;d;}" file2
done < <(awk '{printf "%s\0", $1}' file1 | sed 's|[][\\/.*^$]|\\&|g')

Причина разграничения на нуль-байты, а не на новые строки, заключается в том, что обычно это лучший способ.

Редактировать: Обновлено, чтобы цитировать специальные символы с \ soed не будут работать неправильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...