Considere o seguinte arquivo de entrada:
1
2
3
4
Corrida
{ grep -q 2; cat; } < infile
não imprime nada. Eu esperava que fosse impresso
3
4
Posso obter a saída esperada se a alterar para
{ sed -n 2q; cat; } < infile
Por que o primeiro comando não imprime a saída esperada?
É um arquivo de entrada procurável e de acordo com o padrão em OPTIONS :
-q
Quiet. Nothing shall be written to the standard output, regardless of
matching lines. Exit with zero status if an input line is selected.
e mais abaixo, em USO DO APLICATIVO (enfatize o meu):
A
-q
opção fornece um meio de determinar facilmente se um padrão (ou sequência) existe ou não em um grupo de arquivos. Ao pesquisar vários arquivos, ele fornece uma melhoria de desempenho ( porque pode sair assim que encontrar a primeira correspondência ) [...]
Agora, pelo mesmo padrão (em Introdução , em INPUT FILES )
Quando um utilitário padrão lê um arquivo de entrada procurável e termina sem erro antes de chegar ao final do arquivo, o utilitário deve garantir que o deslocamento do arquivo na descrição do arquivo aberto seja posicionado corretamente logo após o último byte processado pelo utilitário [. ..]
tail -n +2 file
(sed -n 1q; cat) < file
...
O segundo comando é equivalente ao primeiro apenas quando o arquivo é procurável.
Por que grep -q
consome o arquivo inteiro?
Isso é gnu grep
importante (embora o Kusalananda tenha confirmado o mesmo no OpenBSD)
grep
é um fork de algo chamado FreeGrep , se alguém se perguntar.Respostas:
grep
pára cedo, mas armazena em buffer suas entradas, para que seu teste seja muito curto (e sim, percebo que meu teste é imperfeito, pois não é possível procurar):começa em 6776 no meu sistema. Isso corresponde ao buffer de 32KiB usado por padrão no GNU grep:
saídas
Observe que o POSIX menciona apenas melhorias de desempenho
Isso não cria expectativas para melhorias de desempenho devido à leitura parcial de um único arquivo.
fonte
Obviamente, isso se deve ao buffer que
grep
faz para acelerar as coisas. Existem ferramentas projetadas especificamente para ler quantos caracteres forem solicitados e não mais. Um deles éexpect
:Eu não tenho um sistema para testar isso, mas acredito que
expect
irá consumir tudo até encontrar a string esperada (2
) e terminar, deixando o restante da entrada paracat
.fonte
Você está confundindo sed e grep.
Para o comando sed,
-2q
está dizendo para sair da iteração atual, se na segunda linha, a-n
opção está dizendo para funcionar silenciosamente, para que você obtenha todas as linhas após a 2ª.O comando grep é executado por padrão para gerar todas as linhas correspondentes - mas a
-q
opção diz para não gerar nada para stdout. portanto, se a entrada contiver um "2", ela terá um valor de saída SUCCESS, caso contrário FAILURE. O que são depende do seu sistema operacional e shell. Portanto, normalmente você diria se uma linha corresponde examinando o valor de saída do processo grep. Isso é útil em um pipeline no qual você deseja saber se sua entrada contém algum valor como teste. Por exemploNesse caso, não gostamos de ver todas as linhas correspondentes, apenas nos importamos se houver pelo menos uma. O
report_crash_via_email
processo / função pode então sair e reabrir o arquivo, ou não.Se você deseja que seu processo grep PARE depois de encontrar o caractere "2" - ele não será por padrão, ele inspecionará todas as linhas procurando ver se elas correspondem - você precisa dizer para fazer isso. A opção de linha de comando para isso é
-m <value>
. Então, para o seu casogrep -q -m1 2
.fonte
grep
mas esta pergunta é sobre algo mais sutil e esotérico. Parece que você leu a pergunta muito rapidamente para entender o comportamento real que está sendo consultado. Além disso, GNUgrep
faz parar a busca quando usado com-q
(conforme permitido na citação a partir da especificação POSIX): A página man para os estados do GNU grep que “Exit [s] imediatamente com status de zero se qualquer correspondência for encontrada” . FWIW, editei sua pergunta para mostrar como você pode formatar postagens futuras. Welcom para Stack Exchange .grep
está sendo perguntado se '2' existe no arquivo, nada mais e nada menos. Ele não se comportased
e consome registros até esse ponto e deixa o restante para processamento adicional. Ele lê até saber que existe um '2' ou não, fecha o arquivo e retorna o resultado.grep
na verdade, apenas 'consome o arquivo inteiro' (ignorando considerações de buffer) se a cadeia de pesquisa não estiver presente no arquivo (o que é possível apenas examinando o arquivo inteiro). Qualquer coisa menos que isso, a leitura do arquivo é interrompida , o arquivo é fechado e SUCCESS retornado.