Znajdź dowolne linie przekraczające określoną długość


Odpowiedzi:


87

W kolejności malejącej prędkości (w systemie GNU w ustawieniach regionalnych UTF-8 i na wejściu ASCII) zgodnie z moimi testami:

grep '.\{80\}' file

perl -nle 'print if length$_>79' file

awk 'length>79' file

sed -n '/.\{80\}/p' file

Z wyjątkiem perljednej (lub implementacji awk/ grep/ sed(jak mawklub busybox), które nie obsługują znaków wielobajtowych), która liczy długość pod względem liczby znaków (zgodnie z LC_CTYPEustawieniem regionalnym) zamiast bajtów .

Jeśli na wejściu znajdują się bajty, które nie stanowią części prawidłowych znaków (co zdarza się czasami, gdy zestaw znaków ustawień regionalnych to UTF-8, a dane wejściowe mają inne kodowanie), to w zależności od rozwiązania i implementacji narzędzia te bajty będzie liczony jako 1 znak lub 0 lub nie będzie pasował ..

Na przykład linia składająca się z 30 abajtów 0x80, 30 bs, bajtu 0x81 i 30 UTF-8 és (zakodowanych jako 0xc3 0xa9) w ustawieniach regionalnych UTF-8 nie byłaby zgodna .\{80\}z GNU grep/ sed(ponieważ ten samodzielny bajt 0x80 nie pasuje .), miałby długość 30 + 1 + 30 + 1 + 2 * 30 = 122 z perllub mawk, 3 * 30 = 90 z gawk.

Jeśli chcesz liczyć w bajtach, popraw ustawienia regionalne na za Cpomocą LC_ALL=C grep/awk/sed....

To znaczy, że wszystkie 4 rozwiązania uważają, że powyższy wiersz zawiera 122 znaki. Z wyjątkiem perlnarzędzi GNU i nadal możesz mieć potencjalne problemy z wierszami zawierającymi znaki NUL (bajt 0x0).


¹ na perlzachowanie może mieć jednak wpływ PERL_UNICODEzmienna środowiskowa


Co rozumiesz przez „wydajny”?
rowantran

Myślę, że manatwork oznacza efektywność pisania. awkmoże podejść bliżej, jeśli upuścisz ($0), co i tak jest domniemane;).
Thor

9
BTW, jeśli zakotwiczymy wyrażenie regularne na początku linii ^, jest to nieco szybsze: np grep '^.\{80\}' file.
cas

4
Rozwiązanie perla nie uwzględnia kodowania o zmiennej wielkości, takiego jak UTF-8, w przeciwieństwie do wszystkich innych rozwiązań.
BatchyX

6
Wystarczająco duże wartości N zawodzą przy grep, ale odnoszą sukces przy awk. (np. grep '^.\{1000\}' filewraca grep: invalid repetition count(s), ale się awk 'length>1000' fileudaje.)
mdahlman,

1

Podejście do powłoki:

while IFS= read -r line || [ -n "$line" ];
do 
    [ "${#line}" -gt 79 ] && printf "%s\n" "$line"
done < input.txt

Podejście Python:

python -c 'import sys;f=open(sys.argv[1]);print "\n".join([ l.strip() for l in f if len(l) >79 ]);f.close()' input.txt

Lub jako krótki skrypt dla czytelności:

#!/usr/bin/env python
import sys

with open(sys.argv[1]) as f:
    for line in f:
        if len(line) > 79:
            print line.strip()

Jeśli chcemy, aby wykluczyć znak nowego wiersza \nz obliczeń, możemy if len(line) > 79byćif len(line.strip()) > 79

Uwaga dodatkowa: jest to składnia języka Python 2.7. Użyj print()dla Python 3

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.