Jak mogę zidentyfikować linie w plikach na określonej długości

12

Chciałbym znaleźć wiersze w moim kodzie, które przekraczają określoną długość. Mój kod jest w wielu plikach. Jak to zrobić?

Chciałbym poznać pliki i numery linii; treść byłaby preferowana, ale niekonieczna. Celem tego ćwiczenia jest ustalenie, jak przełamać linie (prawdopodobnie ręcznie).

Marcin
źródło
Jak chcesz wyniki? Jako same linie (ich zawartość, jak w grep), lub jako numery linii, lub jako coś innego (być może chcesz zastosować wobec nich inną akcję)? Prawdopodobnie najwygodniejszy sposób na zrobienie tego zależy od tego, co zostanie zrobione z następnymi liniami.
imz - Ivan Zachharyaschev
@ imz - IvanZakharyaschev Dobra uwaga. Pytanie zaktualizowane.
Marcin

Odpowiedzi:

13

Z grep:

grep -En '.{12}' file

Dla linii o długości co najmniej 12 znaków.

Z kilkoma plikami:

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

Niektóre grepimplementacje, takie jak GNU grep, mogą same wyszukiwać pliki.

grep -rEn '.{12}' .

Ale uważaj na dowiązania symboliczne i inne nieregularne pliki.

Stéphane Chazelas
źródło
Podoba mi się to, ponieważ jest to proste, i miałem nadzieję zrobić coś takiego (wciąż się nie przyzwyczaiłem).
Marcin
12

Rozwiązanie AWK

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

Lub, bardziej zwięźle:

awk 'length > 5' file
Ramesh
źródło
9
Możemy skrócić Twoją wersjęawk 'length > 5'
cuonglm
Gnouc jest zabójcą aparatu;)
Ouki
1
+1 dlaawk 'length > 5'
3
Z GNU awkjest nieco mniej elegancki, ale zwięzłyawk '/^.{6,}/'
iruvar
3
@ 1_CR, to POSIX i można go skrócić awk '/.{6}/'(właściwie GNU awk do niedawna był tym, w którym to nie działałoby, chyba że przekażesz POSIXLY_CORRECT do jego środowiska).
Stéphane Chazelas
5

Ponieważ brakowało tylko jednego sedrozwiązania

sed -n '/^.\{6,\}/p' file
iruvar
źródło
5

Rozwiązanie Bash

#!/bin/bash

count=0

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

Więc np ./whatever.sh < input.file. Nie obejmuje to nowej linii przez odjęcie 1 od $len; jeśli nie jest to pożądane lub twoje dane wejściowe używają zakończeń CRLF, powinieneś odpowiednio dostosować.

Złotowłosa
źródło
1
dlaczego nie ${#line}uniknąć exprwidelca?
iruvar
1
ha ha, +1 dla czystego bashroztworu. Pamiętaj jednak, że jeśli nie zostaniesz IFS=przed read, spacje wiodące zostaną zignorowane.
iruvar
1
Dodano kilka dobrych praktyk bash. Pamiętaj również, że nowy wiersz nie jest uwzględniany, $linewięc nie musisz go odejmować.
iruvar
2
@ 1_CR w rzeczywistości, jeśli nie podasz readnazwy do odczytania, będzie ona odczytywać REPLYi zawierać wszystkie białe znaki. Nie IFSwymaga ustawienia.
kojiro
2
To będzie bardzo powolne i specjalnie obsługuje znaki odwrotnego ukośnika. while readpętle do przetwarzania tekstu to naprawdę zła praktyka.
Stéphane Chazelas
4

Za pomocą perl(na przykład), zakładając, że szukasz linii dłuższych niż 80 znaków:

Aby wyświetlić linie:

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

Aby wyświetlić numer linii:

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

Lub obie:

$ perl -nle 'print "[$.]:  $_\n" if length > 80' your_file
Ouki
źródło
3
Powinieneś dodać -llinię poleceń, perlpoliczy podział linii w twoich liniach.
cuonglm
1

Rubin:

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

Python:

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

Oto inne rozwiązanie 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

Powstała tablica jest rzadka, więc wskaźniki tablicy są zachowane. Odkąd zaczęliśmy od 1, indeksy są numerami linii, które trzymaliśmy. Możemy wyprowadzić tylko te numery linii:

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

Lub możemy wyprowadzić same linie:

printf '%s\n' "${MAPFILE[@]}"
kojiro
źródło