Comparando dois arquivos linearmente e se o padrão do arquivo 1 não for encontrado (total ou parcialmente) no arquivo 2, imprima a linha do arquivo 1

3

Eu tenho dois arquivos:

arquivo1 (pesquisa):

1  
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT  
2  
GACGGAGGATGCAAGTGTTATCCGGAAT  
3  
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCC  
4  
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG 

arquivo2 (padrões):

GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGC
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCG
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCC
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCCGTAG 

O que eu preciso é:

1  
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT  
2  
3  
4  
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG  

O que significa que preciso de um script que pesquise minhas linhas de pesquisa no arquivo patterns e, se as linhas de pesquisa puderem ser encontradas total ou parcialmente (como na linha que segue "2"), elas não devem ser escrito, mas todas as outras linhas do arquivo 1.

Eu experimentei muitos dos scripts grep e awk encontrados nesse fórum, mas nenhum deles fez o que eu preciso, por exemplo,

awk 'FN==NR {exclude[$0];next} !($0 in exclude)' file2 file1  

ou

awk 'NR==FNR{a[$1]++;next} !($1 in a) {print $1} {next}' file2 file1

Eu também tentei o grep.

De qualquer forma, todos os scripts tentados encontram os padrões totalmente correspondentes, mas não os que correspondem parcialmente ...

Alguém tem uma ideia?

    
por MSt 12.03.2018 / 10:44

3 respostas

2

Usando um script awk :

NR == FNR       { seq[++n] = $1; next }

{
    header = $0
    getline

    for (i = 1; i <= n; ++i) {
        if (match(seq[i], $0) > 0) {
            print header
            next
        }
    }

    print header
    print
}

Executando:

$ awk -f script.awk file2 file1
1
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT
2
3
4
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG

O script lê primeiro as sequências 2000 de file2 na matriz seq e, em seguida, lê o cabeçalho de file1 seguido pela sequência de file1 (usando getline ). Em seguida, ele passa pelo array seq para encontrar uma seqüência que contém a seqüência atual de file1 . Se essa sequência for encontrada, o cabeçalho será impresso e o script continuará com a próxima linha em file1 . Caso contrário, o cabeçalho e a sequência são impressos.

O script pressupõe que file1 contém linhas de cabeçalho e sequência alternadas e absolutamente nenhuma sequência de várias linhas.

O seguinte é o mesmo script, mas usando o princípio DRY ("Não se repita"):

NR == FNR       { seq[++n] = $1; next }

{
    header = $0
    getline

    found = 0
    for (i = 1; i <= n; ++i) {
        if (match(seq[i], $0) > 0) {
            found = 1
            break
        }
    }

    print header
    if (!found) print
}
    
por 12.03.2018 / 15:01
0
Solução

awk + grep :

awk '/^[^>0-9]/{ 
         m = ""; cmd = sprintf("grep -m1 %s file2", $0);
         cmd | getline m; close(cmd);
         if (m) next; 
     }1' file1
  • cmd - crucial grep command
  • m - variável preenchida com possível item correspondente

A saída:

1
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT
2
3
4
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG
    
por 12.03.2018 / 11:16
0
grep -vxf <(grep -of file_1 file_2 | sort -u) file_1

file_1

1
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT
2
GACGGAGGATGCAAGTGTTATCCGGAAT
3
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCC
4
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG

file_2

GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGC
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCG
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCC
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGCGTCCGTAG

Resultado

1
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCGTAAAGTTTTTTTTT
2
3
4
GACGGAGGATGCAAGTGTTATCCGGAATCACTGGGCCGTCCGTAG
    
por 12.03.2018 / 22:51