Se eu tiver alguma entrada, é melhor filtrar os dados antes de executar minha awk
ação ou devo fazer toda a filtragem awk
?
Por exemplo, dada a seguinte entrada:
$ echo "foo\nbar\nbaz"
foo
bar
baz
Devo correr:
$ echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo cats
Ou:
$ echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo cats
- Por que devo executar qualquer um deles?
- Devo usar uma ferramenta diferente?
- Que fatores devo considerar?
- Como posso testar esses fatores?
Responder1
Neste caso específico, a segunda opção é a melhor.
Em geral, é mais eficiente minimizar o número de utilidades num pipeline. É melhor não bifurcar (iniciar) processos desnecessários (como no seu primeiro exemplo com um sed
processo desnecessário). Na Internet não é difícil encontrar exemplos de reclamações sobreusos inúteis do gato.
Com a maioria dos sistemas modernos do tipo Unix * , a bifurcação é realizada de forma bastante eficiente, mas depende do tamanho do processo que está sendo iniciado, por exemplo, iniciando perl
ou python
seria muito mais lento que sed
ou awk
.
Para comandos únicos, isso não importa muito – mas se o seu pipeline estiver dentro de um loop e sendo executado várias vezes, a remoção de processos desnecessários do seu pipeline poderá acelerar drasticamente o tempo total de execução.
Perguntas específicas
Por que devo executar qualquer um deles?
Se você estiver mais familiarizado com a sintaxe de um em vez do outro, pode ser melhor para a legibilidade (e manutenção) do código usar a ferramenta/linguagem com a qual você está mais familiarizado.
Devo usar uma ferramenta diferente?
Neste caso específico, eu não pensaria assim. Ambos awk
e sed
são ferramentas adequadas para este tipo de trabalho.
Que fatores devo considerar?
Se você tiver que processar vários arquivos (por exemplo, em um loop), a velocidade/eficiência seria importante.
Se você estiver processando apenas um arquivo grande, de vez em quando, a legibilidade do código poderá ser mais importante.
Como posso testar esses fatores?
Você pode criar perfis de diferentes versões usando o time
utilitário, disponível como shell integrado ao Bash – mas também como um programa executável independente. Por exemplo, executar os dois comandos de exemplo mostra que o primeiro exemplo demorou 0,012s a mais que o segundo.
$ time echo "foo\nbar\nbaz" | sed 1q | awk '{ print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.056s
user 0m0.000s
sys 0m0.045s
$ time echo "foo\nbar\nbaz" | awk 'NR == 1 { print $0 " cats" }'
foo\nbar\nbaz cats
real 0m0.044s
user 0m0.000s
sys 0m0.031s
Observe que os benchmarks de criação de perfil são afetados pela carga do sistema e outros fatores limitantes, portanto, você precisará repetir isso um grande número de vezes para obter uma imagem real de qual versão é mais rápida que a outra.
* Com MS Windows, bifurcaçãoémais caro, portanto, minimizar o número de processos iniciados faz diferença ao executar em ambientes como o Cygwin.
Responder2
É o suficiente para usarestranho(oused) ferramenta para casos tão simples. Uma combinação de múltiplas ferramentas seria muito complicada e muitas vezes redundante:
echo -e "foo\nbar\nbaz" | awk 'NR==1{print $0" cats"}'
A saída:
foo cats
Que fatores devo considerar?
Certifique-se de que o processamento de texto necessário requer a combinação de várias ferramentas diferentes; caso contrário, use o poder de uma ferramenta distinta
Digamos que se eu precisar apenas adicionar uma determinada palavra antes da primeira palavra na string de entrada - também é fácil comsedferramenta:
echo -e "foo\nbar\nbaz" | sed 's/^.*$/& cats/; 1q'
foo cats
echo -e
, e
sinalizador "permite a interpretação de escapes de barra invertida"
De qualquer forma, depende de quão complexo é o seu texto de entrada e quão sofisticadas são as suas regras de processamento de texto