Como encontrar linhas contendo uma string e depois imprimir essas linhas específicas e outra coisa

0

Eu uso o seguinte comando para pesquisar recursivamente vários arquivos e encontrar o número da linha em cada arquivo no qual a string é encontrada.

    grep -nr "the_string" /media/slowly/DATA/lots_of_files > output.txt

A saída é a seguinte:

    /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt:3:the_string
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:6:the_string is in this sentence.
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:9:the_string is in this sentence too.

Como mostrado acima, a saída inclui o nome do arquivo, o número da linha e todo o texto nessa linha, incluindo a string.

Eu também descobri como imprimir apenas as linhas específicas de um arquivo contendo a string usando o seguinte comando:

    sed '3!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt > print.txt
    sed '6!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt
    sed '9!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt

Eu criei os comandos acima manualmente, lendo os números de linha e os nomes dos arquivos

Aqui está a minha pergunta.

Q1a

Existe uma maneira de combinar as duas etapas em um único comando? Estou pensando em colocar o número da linha e o nome do arquivo em sed e imprimir a linha. Estou tendo um problema com a ordem em que a saída do grep é gerada.

Q1b

O mesmo que acima, mas também imprime as 2 linhas antes e 2 linhas depois da linha que contém a string (total de 5 linhas)? Estou pensando em colocar o número da linha e o nome do arquivo em sed e imprimir todas as linhas necessárias de alguma forma.

Muito obrigado.

    
por speld_rwong 27.12.2016 / 22:32

3 respostas

2

Se eu estou entendendo a pergunta corretamente, você pode fazer isso com um comando grep.

Para a primeira parte, sua saída grep pode suprimir o nome do arquivo usando -h , por exemplo:

grep -hnr "the_string" /media/slowly/DATA/lots_of_files > output.txt

Para Q1b, sua saída grep pode incluir linhas precedendo e seguindo linhas correspondentes usando -A e -B , por exemplo:

grep -hnr -A2 -B2 "the_string" /media/slowly/DATA/lots_of_files > output.txt

A saída conterá um separador entre correspondências, que você pode suprimir com --no-group-separator , por exemplo:

grep -hnr -A2 -B2 --no-group-separator "the_string" /media/slowly/DATA/lots_of_files > output.txt

Observe que a saída usa um delimitador diferente para linhas correspondentes ( : ) e linhas de contexto ( - ).

    
por 27.12.2016 / 23:12
0

Sua primeira pergunta, até onde eu sei, pode ser respondida em grep de uma maneira diferente. Quando você envia uma lista de arquivos (ou diretório para recorrer com -r ou -R ), ele sempre mostrará em qual arquivo encontrou uma correspondência, bem como o número da linha. Você pode contornar isso com um constructo como:

find /path/to/files -type f | xargs grep -n 'the_pattern'

Quanto à sua segunda pergunta, se você quiser ver as linhas antes e depois da correspondência, use a opção -C (para C ontext):

grep -C2 'pattern' /path/to/file # displays the two lines before and after a match

Relacionados a -C são -A (para A fter) e -B (para B antes), que fornecem apenas o número especificado de linhas depois ou antes de uma partida, respectivamente.

Você pode combinar as duas respostas assim:

find /path/to/files -type f | xargs grep -n -C2 'the_pattern'

Quanto à sua pergunta sobre sed , o exemplo que você deu funciona somente se você já conhece os números de linha. Você também pode fazer algo como:

sed -n '/the_pattern/p' /path/to/files/*

(mas não recorrerá a subdiretórios)

    
por 27.12.2016 / 23:02
0
find /media/slowly/DATA/lots_of_files -type f -exec grep -h -C2 'the_pattern' {} +

Isto irá encontrar coisas que são arquivos (ao contrário de diretórios ou links) sob o diretório / media / slowly / DATA / lots_of_files. Ele irá agrupá-los (sem necessidade de xargs nesta década) e executar grep neles. grep não imprimirá os nomes dos arquivos (-h), mas dará 2 linhas de contexto antes e depois das linhas correspondentes (-C2, use -A e -B para um controle mais preciso).

A vantagem deste comando em relação ao de @cherdt é que você pode adicionar filtros adicionais ao comando find, por exemplo, você pode optar por não entrar em diretórios como .git

    
por 27.12.2016 / 23:40