Quando devo usar o redirecionamento de entrada?

20

Eu usei os dois comandos a seguir para produzir os mesmos resultados: -

[root@localhost ~]# grep line comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

[root@localhost ~]# grep line <comments
The line should start with a single quote to comment in VB scripting.
Double slashes in the beginning of the line for single line comment in C.
[root@localhost ~]#

Alguém poderia me explicar qualquer prós / contras se qualquer uma dessas duas abordagens se sobrepõem.

    
por Ankit 01.04.2013 / 13:59

2 respostas

27

Da página man grep (no Debian):

DESCRIPTION

   grep  searches the named input FILEs (or standard input if no files are
   named, or if a single hyphen-minus (-) is given as file name) for lines
   containing  a  match to the given PATTERN.  By default, grep prints the
   matching lines.

No primeiro caso, grep abre o arquivo; no segundo, o shell abre o arquivo e o atribui à entrada padrão de grep , e grep não sendo passado a nenhum argumento de nome de arquivo, pressupõe que ele precisa ajustar sua entrada padrão.

Prós de 1:

  • grep pode utilizar mais de um arquivo¹.
  • grep pode exibir o nome do arquivo onde cada ocorrência de line é encontrada.

Prós de 2:

  • Se o arquivo não puder ser aberto, o shell retornará um erro que incluirá informações mais relevantes (como o número da linha no script) e de uma maneira mais consistente (se você permitir que os arquivos abertos do shell também sejam usados para outros comandos) ) do que quando grep abre. E se o arquivo não puder ser aberto, grep não é nem chamado (o que para alguns comandos - talvez não grep - pode fazer uma grande diferença).
  • em grep line < in > out , se in não puder ser aberto, out não será criado nem truncado.
  • Não há problemas com alguns arquivos com nomes incomuns (como - ou nomes de arquivos que começam com - ) ².
  • cosmético: você pode colocar <file em qualquer lugar na linha de comando para mostrar o fluxo de comando mais naturalmente, como <in grep line >out , se preferir.
  • cosmético: com o GNU grep , você pode escolher o rótulo a ser usado na frente da linha correspondente, em vez de apenas o nome do arquivo, como em:

    <file grep --label='Found in file at line' -Hn line
    

Em termos de desempenho, se o arquivo não puder ser aberto, você salvará a execução de grep ao usar o redirecionamento, mas, por outro lado, para grep , não espero muita diferença.

Com o redirecionamento, você não precisa passar um argumento extra para grep , você torna a análise de argumentos de grep um pouco mais fácil. Por outro lado, o shell precisará (pelo menos) de uma chamada extra do sistema para dup2() do descritor de arquivo no descritor de arquivo 0.

Em { grep -m1 line; next command; } < file , grep (aqui GNU grep ) desejará seek() de volta para logo após a linha correspondente, então o next command verá o restante do arquivo (também será necessário determinar se o arquivo é procurado ou não). Em outras palavras, a posição dentro de stdin é outra da saída de grep . Com grep -m1 line file , pode otimizar isso, isso é uma coisa a menos para grep se importar.

Notas

¹ Com zsh , você pode fazer:

grep line < file1 < file2

mas que está fazendo o equivalente a cat file1 file2 | grep line (sem invocar o utilitário cat ) e, portanto, é menos eficiente, pode causar confusão se o primeiro arquivo não terminar em um caractere de nova linha e não o informar qual arquivo o padrão é encontrado.

² No caso de ksh93 e bash , existem arquivos como /dev/tcp/host/port (e /dev/fd/x em alguns sistemas em bash ) que, quando usados no destino de redirecionamentos que o shell intercepta para propósitos especiais em vez de realmente abrir o arquivo no sistema de arquivos (embora, geralmente, esses arquivos não existam no sistema de arquivos). /dev/stdin tem o mesmo propósito que - reconhecido por grep , mas pelo menos aqui é mais apropriadamente namespaced (qualquer um pode criar um arquivo chamado - em qualquer diretório, enquanto apenas administradores podem criar um arquivo chamado /dev/tcp/host/port e os administradores devem saber melhor).

    
por 01.04.2013 / 14:13
6

A resposta de StephaneChazelas cobre grep(1) , e a maioria dos comandos de linhagem Unix funcionam assim, mas não todos. É padrão ler a partir da entrada padrão (do teclado, de um arquivo redirecionado via < file ou da saída canalizada por outro comando, exemplo estúpido ls * | grep '^ab*c$' ) ou do (s) arquivo (s) fornecido (s) como argumentos, como grep comment file1 file2 file3 . Alguns comandos usam a convenção de que o arquivo chamado - é a entrada padrão, portanto, você pode dizer make-middle | cat head - tail para obter um fluxo com head , independentemente do gen-middle gerado, seguido por tail . Isso é por design, para dar flexibilidade no uso dos comandos.

Qual é o melhor? Contanto que funcione, cmd file é menor que cmd < file ; poderia haver uma diferença minúscula no tempo entre o shell fazendo o arquivo frobbing ( < ) e o comando fazendo isso sozinho, mas provavelmente imperceptível a menos que você não faça nada mais o dia todo. Dependerá de considerações como os profissionais mencionados na resposta de Stephane.

    
por 01.04.2013 / 16:03