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).


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.


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

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

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ć.


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

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

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[@]}"
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.