Mostrar todo o arquivo até o fósforo

54

grep --before-context 5 mostra 5 linhas antes do jogo.

Quero mostrar tudo antes do jogo.
Fazer grep --before-context 99999999 funcionaria, mas não é muito ... profissional.

Como mostrar todo o arquivo até a partida?

    
por Nicolas Raoul 14.04.2011 / 11:32

7 respostas

74

Sed é melhor para isso.

Basta fazer:

sed '/PATTERN/q' FILE

Funciona assim:

Para cada linha, verificamos se ela corresponde a /PATTERN :

  • se sim, imprimimos e saímos
  • caso contrário, imprimimos

Esta é a solução mais eficiente, porque assim que ela for vista PATTERN , ela será encerrada. Sem q , sed continuaria a ler o restante do arquivo e não faria nada com ele. Para arquivos grandes, isso pode fazer a diferença.

Esse truque também pode ser usado para emular head :

sed 10q FILE
    
por 14.04.2011 / 11:42
29

sed pode substituir a maior parte da funcionalidade do grep.

sed -n '1,/<pattern>/ p' <file>

Isso significa imprimir da primeira linha até que o padrão seja correspondido.

Alguns exemplos de intervalos

sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2
    
por 14.04.2011 / 11:43
26

imprima até e inclua a correspondência:

awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename

imprima até MAS NÃO incluindo a correspondência:

awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename
    
por 14.04.2011 / 15:20
1

Os seguintes métodos pure% GNUgrep não são eficientes.

Pesquise tudo até a primeira instância da string " foo " no arquivo bar , usando três grep s:

grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar

Correspondência com a última instância de " foo ":

grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar

Observação: os detalhes sobre os últimos grep podem ser encontrados em: Regex (grep) para pesquisa de várias linhas necessária .

    
por 14.10.2016 / 14:24
1

Para pessoas que optam por lembrar apenas as ferramentas básicas no trabalho do dia a dia e que aceitam soluções menos elegantes e menos eficientes:

head -n $(grep -n pattern filename | cut -d: -f1) filename

Se este comando for para um script, procurarei soluções mais elegantes (e possivelmente eficientes). Se este é um comando de uma vez ou um script de jogar fora, então eu não me importo.

    
por 14.04.2011 / 11:45
0

Você também pode usar uma das seguintes opções

tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac 

ou

tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac

ou

tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac

A primeira opção é muito semelhante ao que o OP sugeriu apenas certifica-se de mostrar linhas suficientes antes do contexto contando as linhas no arquivo

A segunda opção procura o número da linha da primeira partida (você pode mudar isso também mudando a 'cabeça' interna) e então usa a cabeça naquele número

A última opção substitui todas as novas linhas pela correspondência e substitui duas correspondências adjacentes por uma nova. A saída disso é uma linha para cada bloco de texto entre duas correspondências. Depois disso, ele usa 'head' para escolher a primeira linha (convertendo o bloco de texto até a primeira partida) e então traduz cada partida para uma nova linha. esta opção só funciona se o arquivo estiver no seguinte formato

pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern 
texttexttext
texttexttexttexttexttexttexttexttext

e assim por diante

    
por 09.07.2015 / 21:29
0

Adicionando a resposta de Mikel acima ...

Para imprimir todas as linhas até, mas não incluindo , a primeira linha em FILE contendo PATTERN , tente:

  • sed '/.*PATTERN.*/{s///;q;}' FILE

Isso corresponde à linha inteira que contém o padrão, substitui-a por uma linha em branco e, em seguida, sai sem processar o restante do arquivo.

Post-script:

A maneira mais fácil / mais clara que consegui evitar para imprimir uma nova linha no final (sem envolver outra ferramenta) foi executar o sed novamente e excluir a nova linha final:

sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'

... e como agora estamos excluindo essa linha, nosso trabalho anterior é redundante e podemos simplificar para:

sed '/PATTERN/q' FILE | sed '$d'
    
por 12.12.2017 / 21:21