Quando devo usar o redirecionamento de entrada?


21

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 ~]#

Qualquer um poderia por favor me explicar quaisquer prós / contras, se algum destes 2 se aproximar um do outro.

Respostas:


28

Na man greppágina (no Debian):

DESCRIÇÃO

   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, grepabre o arquivo; no segundo, o shell abre o arquivo e o atribui à entrada padrão de grep, e grepnão sendo transmitido nenhum argumento de nome de arquivo, pressupõe que ele precise cumprimentar sua entrada padrão.

Prós de 1:

  • grep pode receber mais de um arquivo¹.
  • greppode exibir o nome do arquivo em que cada ocorrência 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 número da linha no script) e de maneira mais consistente (se você permitir que o shell abra arquivos para outros comandos também) do que quando grepabre. E se o arquivo não puder ser aberto, grepnem será chamado (o que para alguns comandos - talvez não grep- possa fazer uma grande diferença).
  • em grep line < in > out, se innão pode ser aberto, outnão será criado ou truncado.
  • Não há problema com alguns arquivos com nomes incomuns (como -nomes de arquivos ou começando com -) ².
  • cosmético: você pode colocar <fileem qualquer lugar da linha de comando para mostrar o fluxo de comando com mais naturalidade, como <in grep line >outse preferir.
  • cosmético: com o GNU grep, você pode escolher qual rótulo usar 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ê salva a execução grepao usar o redirecionamento, mas, caso contrário grep, não espero muita diferença.

Com o redirecionamento, você economiza a necessidade de passar um argumento extra para grepfacilitar grepa análise do argumento. Por outro lado, o shell precisará (pelo menos) de uma chamada extra do sistema para dup2()o descritor de arquivo no descritor de arquivo 0.

Em { grep -m1 line; next command; } < file, grep(aqui o GNU grep) desejará seek()retornar logo após a linha correspondente, para que next commandveja o restante do arquivo (ele também precisará determinar se o arquivo é procurável ou não). Em outras palavras, a posição dentro de stdin é outra da grepsaída. Com grep -m1 line fileisso, ele pode otimizar isso, é menos uma coisa para grepse preocupar.


Notas

¹ Com zsh, você pode fazer:

grep line < file1 < file2

mas isso equivale a cat file1 file2 | grep line(sem chamar o catutilitário) e, portanto, é menos eficiente, pode causar confusão se o primeiro arquivo não terminar em um caractere de nova linha e não informar em qual arquivo o padrão foi encontrado.

² No caso ksh93e no bashentanto, existem arquivos como /dev/tcp/host/port(e /dev/fd/xem alguns sistemas bash) que, quando usado no destino de redirecionamentos, o shell intercepta para fins especiais, em vez de realmente abrir o arquivo no sistema de arquivos (embora geralmente esses arquivos não existe no sistema de arquivos). /dev/stdinserve para o mesmo propósito que o -reconhecido por grep, mas pelo menos aqui está no espaço para nome mais adequado (qualquer pessoa pode criar um arquivo chamado -em qualquer diretório, enquanto apenas os administradores podem criar um arquivo chamado /dev/tcp/host/porte os administradores devem saber melhor).


+1, para uma boa explicação. Eu tenho uma dúvida: no segundo caso, quando o shell abre o arquivo, ele passa o conteúdo do arquivo aberto para a entrada padrão (teclado)? (Fiquei confuso com o termo 'entrada padrão do grep').
Ankit

1
@Ankit, stdin é onde os aplicativos leem sua entrada por padrão, o descritor de arquivo 0. Quando em um terminal, o fd 0 é aberto pela leitura no dispositivo do terminal (algo como / dev / ttyxx ou / dev / pts / n). É assim que eles acabam recebendo o que você digita no teclado. O redirecionamento do shell do stdin de um comando apenas abre o fd 0 para algum outro arquivo antes de executar o comando.
Stéphane Chazelas

6

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

Qual é melhor? Contanto que funcione, cmd fileé menor que cmd < file; pode haver uma pequena diferença de tempo entre o shell fazendo o arquivo frobbing ( <) e o comando fazendo isso por si só, mas provavelmente imperceptível, a menos que você não faça mais nada o dia todo. Vai depender de considerações como os profissionais mencionados na resposta de Stephane.


cmd filenão é mais curto do que cmd<fileembora.
Stéphane Chazelas 02/02

É um toque de tecla mais curto, presumindo que você precise pressionar Shift para digitar a <.
DopeGhoti 16/0518
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.