Quero deletar todas as palavras que são independentes e são vistas 3 vezes ou mais, sem manter a primeira correspondência. Com "permanecer por conta própria", quero dizer a palavra completa. Não é um padrão que faz parte de alguma palavra. Eu descobri, awk '++A[$0] < 3'
mas isso analisa toda a linha, em vez de apenas o padrão. Devo primeiro contar as palavras e depois excluir tudo o que vi 3 vezes ou mais?
Quando procuro isso, trata-se de verificar palavras usando $0
linhas inteiras e excluir a linha se o padrão corresponder. Não apenas palavras/padrões por si só. Não estou apenas procurando por awk. Tudo está bem, exceto perl
hahaha.
Eu também quero excluir Shares for
e [--- Listable Shares ---]
ser excluído. Provavelmente posso encontrar isso sozinho se o comando não for muito complexo. Caso contrário, adicione-o à resposta e dê alguma explicação. Adoro continuar aprendendo aqui
entrada:
Shares for DED-SHD-ED-1:
[--- Listable Shares ---]
backup backup2
Shares for DED-SHD-ED-2:
[--- Listable Shares ---]
ConsoleSetup REMINST SCCMContentLib$ SCCMContentLibC$ SEFPKGC$ SEFPKGD$ SEFPKGE$ SEFSIG$ Source UpdateServicesPackages WsusContent backup backup2
Shares for DED-SHD-BE-03:
[--- Listable Shares ---]
backup backup2 print$
Resultado esperado:
Shares for DED-SHD-ED-1:
[--- Listable Shares ---]
Shares for DED-SHD-ED-2:
[--- Listable Shares ---]
ConsoleSetup REMINST SCCMContentLib$ SCCMContentLibC$ SEFPKGC$ SEFPKGD$ SEFPKGE$ SEFSIG$ Source UpdateServicesPackages WsusContent
Shares for DED-SHD-BE-03:
[--- Listable Shares ---]
print$
Apenas backup
e backup2
são excluídos.
Editar:
print$
como um todo é considerada uma palavra que precisa ser excluída caso seja vista 3 vezes ou mais. Não print
sem$
Espero ouvir de vocês em breve!
Como o requisito abrange arquivos de até 1 MB, há algumas inversões de array para melhorar a eficiência. Como estamos excluindo palavras, não achei importante manter o espaçamento exato; portanto, cada palavra em uma linha substituída é precedida apenas por TAB.
É um script Bash que contém uma única função shell, que contém um único programa awk. Leva um argumento de arquivo de entrada e envia para stdout.
Não tenho certeza de como você deseja verificar os resultados. Tive bastante depuração durante o desenvolvimento: seria fácil (por exemplo) registrar no stderr as palavras excluídas, com sua frequência.
Usando GNU
awk
para o quarto argumento parasplit()
salvar as strings que correspondem a,FS
para que possamos ter o mesmo espaçamento na saída que estava presente na saída:Você pode fazer o mesmo em qualquer awk com um
while ( match(...) )
loop em vez desplit(...); for (...)
, seriam apenas mais algumas linhas de código, por exemplo, isso funcionará em qualquer awk:EDIT: @Paul_Pedant e eu estávamos conversando nos comentários sobre os prós/contras de ler a entrada em um array e depois processá-la na
END
seção como o script dele faz versus ler o arquivo de entrada duas vezes como meu script acima faz, então coloquei o meu um script de shell e adicionou um shebang bash:em seguida, criei um arquivo de entrada com 1 milhão de cópias do arquivo de entrada de 9 linhas do OP fazendo o seguinte:
então cronometramos a execução do meu script nele:
mas quando tentei executar o script de Paul nele:
meu laptop começou a soar como um helicóptero decolando, então depois de 5 minutos eu o interrompi e esperei mais 3 minutos para meu laptop se acalmar novamente.
Em seguida, tentei ambos em um arquivo de 100 mil repetições:
mas novamente tive que interromper Pauls (dei 10 minutos para este).
Então tentei um arquivo de 10 mil repetições:
Desta vez, obtive resultados de ambos, então executei um
diff -b
deles e descobri que a saída é diferente -O meu remove os valores duplicados no final das
Shares for ...
linhas, enquanto o de Paul não. não sei qual seria o comportamento desejado para o OP ou, se for importante, pode ser apenas uma entrada irreal.Então tentei 1k repetições:
e 100 repetições:
então parece que cerca de 1k ou menos repetições dos dados OPs (ou seja, até cerca de um arquivo de entrada de linha de 10k) se você armazena os dados na memória e analisa na seção END ou lê o arquivo de entrada duas vezes é uma lavagem em relação à execução velocidade (quando você estiver no tempo de execução de décimos de segundo, quem se importa?) e em cerca de 10 mil repetições (cerca de 100 mil linhas de entrada), a abordagem de leitura duas vezes é um pouco mais rápida, mas ambas são rápidas em cerca de 1 segundo de tempo de execução. Porém, quando você chegar a tamanhos de arquivo de entrada maiores do que isso, você realmente não vai querer tentar armazená-lo na memória.