Como você remove todas as ocorrências de valores em uma lista de outra lista?

2

Eu tenho uma lista de símbolos como ...

wer
sfe
efo

Como faço para remover todas as instâncias desses símbolos (exclusivos) de outra lista de símbolos (não exclusivos)?

Portanto, na lista a seguir, as linhas que começam com wer serão removidas duas vezes e sfe uma vez:

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

Todas as outras linhas devem permanecer intactas, com o símbolo e os caracteres após "-" restantes:

efr-4siosejf
rte-alskjdfs

Eu preciso fazer isso usando sed / awk / grep / bash ou outras ferramentas de linha de comando. Eu sei como escrever um comando sed para pesquisar e remover um valor de cada vez, mas como faço isso para valores de 100k +?

    
por barrrista 20.11.2012 / 20:02

4 respostas

1

What if file 2 has characters after each of those symbols?  I want to do the same but keep the trailing characters.

OK, faça uma cópia de file2 que tenha apenas o campo que você deseja filtrar. E, se o atual file2 tiver o "símbolo não exclusivo" imediatamente seguido pelos "caracteres finais" (por exemplo, efr-42 , rte-17 , etc.), faça outra cópia de file2 onde eles estão separados por espaços. Aqui estão exemplos de comandos com base nos dados de exemplo que você forneceu:

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

ou

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

… com base nos novos dados que você adicionou à sua pergunta. Em seguida, use comm como antes:

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

… e junte os símbolos aos caracteres finais:

join file2.no_match file2.separated

Se necessário, use outro sed para remover os espaços adicionados.

Ocorreu que você poderia criar esse truque para recuperar o arquivo de saída para o pedido original de file2 .

  1. Produza uma cópia do original file2 com números de linha.
  2. Embaralhe os números de linha à direita dos símbolos.
  3. (acima, começando com os comandos sort )
  4. Classifique a saída no número da linha original.
  5. Exclua os números das linhas.

Deixe-me saber se você precisar de ajuda com isso.

    
por 20.11.2012 / 22:11
2

Assumindo que suas listas residem em arquivos

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

grep também é uma opção

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

O sed bit adiciona uma âncora regular ao início de cada linha.

    
por 21.11.2012 / 00:35
1

Você precisa manter a ordem do seu segundo arquivo? Você pode declarar um número máximo de vezes que uma linha pode ser repetida? Se as respostas para ambas as perguntas forem "não", sugiro 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

Inclua cópias suficientes de file1 em file1.sorted para cobrir o número máximo de ocorrências de qualquer string em file2 .

    
por 20.11.2012 / 20:41
0

Sem saber nada sobre o SED etc, o design básico no meu pseudocódigo pessoal é:

ordena a lista de strings a serem removidas (lista A)

ordena a lista de strings que contém itens a serem removidos (Lista B)

Para cada item na lista 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)

Nota: "Remover" um item pode ser problemático - é melhor substituir essa linha por uma que adicione o item a uma nova

    
por 20.11.2012 / 20:27