Existe um comando de uma linha para imprimir a linha mais longa dentro dos arquivos em um diretório?

4

Vamos supor que estou em um diretório com muitos arquivos. Como você procuraria o conteúdo de todos os arquivos em um diretório e mostraria a linha mais longa que contém a string “ER”, mas não “Cheese”?

Até agora, para o meu melhor conhecimento, estou tentando fazer isso em um comando de linha.

Estou pensando que preciso usar o grep -r para recursivas, a fim de pesquisar em todos os arquivos no diretório mas meu objetivo final é apenas exibir a linha mais longa, então presumo que até agora seja como:

grep -r -e "ER" 

e quando eu faço -v "Cheese" anexado a ele por uma pequena esperança, isso não funciona, é claro.

Isso não é possível com uma linha de comando? Se sim, o que eu precisaria fazer em várias linhas?

    
por jkl0619 24.09.2017 / 03:20

5 respostas

14

Aqui está uma solução para o awk:

 awk '/ER/ && !/Cheese/ {if (length($0) > maxlen) { maxline=$0; maxlen=length($0);}} END {print maxlen, maxline;}' *

(também imprime o comprimento da linha mais longa, mas se você não quiser, diga ... END {print maxline;} .

A vantagem sobre a solução grep de Jeremy Dover é que ela passa por cima da entrada. A desvantagem é que, se houver várias linhas com o mesmo tamanho máximo, ele apenas imprime o primeiro (ou o último, se você usar > = para comparar os comprimentos); a solução grep imprime todos eles.

    
por 24.09.2017 / 05:14
6

Esta linha fará o que você pede (para arquivos em um diretório):

awk '{l=length($0)}/ER/&&!/Cheese/&&(length($0)>l){l=length($0);line=$0}END{print(line)}' *

Se houver várias linhas correspondentes, isso imprimirá somente a linha primeiro que contém ER, não Cheese e é maior que uma linha selecionada anteriormente.

Além disso, isso irá verificar os arquivos no pwd (*). Se você precisar de recursão, os arquivos precisarão ser selecionados com um comando find.

find . -type f -iname '*.sh' -exec sh -c 'awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'' "$@"' awksh {} +

Ou em várias linhas (para legibilidade):

find . -type f -iname '*.sh' -exec sh -c '\
awk '\''{l=length($0)}/ER/&&!/Cheese/&&(l>lm){lm=l;li=$0}END{print(li)}'\'\
' "$@"' awksh {} +
    
por 24.09.2017 / 05:27
6
awk '/ER/ && !/Cheese/ && length > m {
       m=length; d=$0; f=substr(FILENAME, 3); n=FNR
     }
     END { print m, f ":" n, d }' ./*

Supondo que haja apenas arquivos regulares no diretório atual, isso imprimirá o comprimento da linha mais longa que atende aos critérios da pergunta ( m ), juntamente com o nome do arquivo no qual ela foi encontrada ( f ). número da linha ( n ) e a própria linha ( d ).

A saída pode ser algo como

8 file:3 Hello ER

A linha mais longa tinha 8 caracteres e foi encontrada na linha 3 em um arquivo chamado file .

    
por 24.09.2017 / 09:21
3

Eu acredito que o seguinte one-liner deve funcionar:

L='grep -h "ER" * | grep -v Cheese | wc -L'; grep -h "ER" * | grep -v Cheese | grep -P ".{$L}"

O primeiro comando encontra todas as linhas em arquivos no diretório contendo "ER" (você só precisa da opção -R se tiver subdiretórios, senão a glob * é tudo que você precisa), remove as linhas com Cheese, e, em seguida, encontra a mais longa dessas linhas com o comando wc -L .

O segundo comando (infelizmente) realiza a pesquisa por linhas conformes novamente, mas depois procura por linhas do comprimento máximo. Você pode não precisar da opção -P para grep, dependendo da sua versão do grep.

    
por 24.09.2017 / 04:12
2

Um que preenche o comprimento da string, classifica numericamente e imprime o segundo campo do primeiro resultado para recuperar a string original.

 grep -h ER * | grep -v Cheese | awk '{ print length($0) " " $0}' | sort -nr| head -1| awk '{print $2}'    

Essa abordagem permite fazer consultas mais sofisticadas do que "MAX" ou "MIN", se necessário. Observe o uso do AWK. Isso é exatamente o que é realmente bom.

    
por 24.09.2017 / 22:08