Como identificar linhas em arquivos com um determinado comprimento

12

Gostaria de encontrar linhas no meu código que excedam um determinado comprimento. Meu código está em vários arquivos. Qual é uma boa maneira de fazer isso?

Eu gostaria de saber os arquivos e números de linha; o conteúdo seria preferido, mas não necessário. O objetivo do exercício é descobrir como quebrar as linhas (provavelmente manualmente).

Marcin
fonte
Como você quer os resultados? Como as próprias linhas (seu conteúdo, como em grep), ou como números de linha, ou como outra coisa (talvez você queira aplicar outra ação sobre elas)? Provavelmente, a maneira mais conveniente de fazer isso depende do que será feito com essas linhas a seguir.
imz - Ivan Zakharyaschev 27/03
@ imz - IvanZakharyaschev Bom ponto. Pergunta atualizada.
27414 Marcin

Respostas:

13

Com grep:

grep -En '.{12}' file

Para linhas com pelo menos 12 caracteres.

Com vários arquivos:

find . -type f -exec grep -En '.{12}' {} +

Algumas grepimplementações, como o GNU grep, podem fazer a busca por arquivos.

grep -rEn '.{12}' .

Mas cuidado com links simbólicos e outros arquivos não regulares.

Stéphane Chazelas
fonte
Gosto disso porque é simples e esperava fazer algo assim (ainda não cheguei a isso).
286 Marcin
12

Solução AWK

awk '{       
if (length($0) > 5)
        print $0;'} yourfile

Ou, mais concisamente:

awk 'length > 5' file
Ramesh
fonte
9
Podemos encurtar a sua versãoawk 'length > 5'
cuonglm
Gnouc é um assassino de chaves;)
Ouki 27/03
1
1 forawk 'length > 5'
3
Com GNU awka um pouco menos elegante, mas concisaawk '/^.{6,}/'
Iruvar
3
@ 1_CR, Isso é POSIX e pode ser reduzido para awk '/.{6}/'(na verdade, o GNU awk até recentemente costumava ser aquele em que isso não funcionaria, a menos que você passasse POSIXLY_CORRECT para o ambiente).
Stéphane Chazelas 27/03
5

Uma vez que faltava uma sedsolução

sed -n '/^.\{6,\}/p' file
iruvar
fonte
5

Solução Bash

#!/bin/bash

count=0

while read; do
    ((++count)) 
    len=${#REPLY}
    if ((len > 80)); then
        echo "Line $count is $len characters."
    fi
done

Então, por exemplo ./whatever.sh < input.file. Isso não inclui a nova linha subtraindo 1 de $len; se isso não for desejável, ou se sua entrada usa terminações CRLF, você deve ajustar em conformidade.

Cachinhos Dourados
fonte
1
por que não ${#line}evitar o exprgarfo?
iruvar 27/03
1
ha ha, +1 para a bashsolução pura . Mas observe que, a menos que você fique IFS=na frente read, os espaços à esquerda serão ignorados.
iruvar 27/03
1
Adicionado em algumas boas práticas do bash. Observe também que a nova linha não é levada em consideração; $lineportanto, não é necessário subtrair uma.
Iruvar
2
@ 1_CR na verdade, se você não der readum nome para ler, ele lerá REPLYe incluirá todo o espaço em branco. Nenhuma IFSconfiguração é necessária.
Kojiro
2
Isso será extremamente lento e lida especialmente com os caracteres de barra invertida. while readloops para processar texto são realmente uma prática ruim.
Stéphane Chazelas 27/03
4

Com perl(por exemplo), supondo que você esteja pesquisando linhas com mais de 80 caracteres:

Para exibir as linhas:

$ perl -nle 'print if length > 80' your_file

Para exibir o número das linhas:

$ perl -nle 'print "$.\n" if length > 80' your_file

Ou ambos:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file
Ouki
fonte
3
Você deve adicionar -llinha de comando, perlcontará a quebra de linha em suas linhas.
cuonglm
1

Ruby:

ruby -lne 'puts $_ if $_.size > 5' intputfile

Pitão :

python -c "import sys;[ sys.stdout.write(''.join(line)) for line in sys.stdin if len(line.strip()) > 5 ]" < inputfile
Rahul Patil
fonte
1

Aqui está outra solução do bash (bash 4):

minlen=5 # minimum length of a line
mapfile -tO1 < inputfile # Map the file to the array MAPFILE (by default)
                         # Start the array at index 1
for i in "${!MAPFILE[@]}"; do
  (( ${#MAPFILE[i]} > minlen )) || unset MAPFILE[i] # Remove shorter elements
done

A matriz resultante é escassa, portanto, os índices da matriz são mantidos. Desde que começamos com 1, os índices são os números das linhas que mantemos. Podemos gerar apenas esses números de linha:

printf 'Long lines found at: '
printf '%d, ' "${!MAPFILE[@]}"
echo

Ou podemos produzir as próprias linhas:

printf '%s\n' "${MAPFILE[@]}"
kojiro
fonte