Temukan garis yang melebihi panjang tertentu

53

Apakah mungkin menemukan baris dalam file yang melebihi 79 karakter?

rowantran
sumber

Jawaban:

91

Untuk mengurangi kecepatan (pada sistem GNU di lokal UTF-8 dan pada input ASCII) menurut pengujian saya:

grep '.\{80\}' file

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

awk 'length>79' file

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

Kecuali untuk perl¹ satu (atau untuk awk/ grep/ sedimplementasi (suka mawkatau kotak sibuk) yang tidak mendukung karakter multi-byte), yang menghitung panjang dalam hal jumlah karakter (sesuai dengan LC_CTYPEpengaturan lokal) bukan byte .

Jika ada byte dalam input yang tidak membentuk bagian dari karakter yang valid (yang kadang-kadang terjadi ketika set karakter lokal adalah UTF-8 dan input dalam pengkodean yang berbeda), maka tergantung pada solusi dan implementasi alat, byte tersebut akan dihitung sebagai 1 karakter, atau 0 atau tidak cocok ..

Misalnya, sebuah garis yang terdiri dari 30 asa 0x80 byte, 30 bs, 0x81 byte dan 30 UTF-8 é(disandikan sebagai 0xc3 0xa9), di lokal UTF-8 tidak akan cocok .\{80\}dengan GNU grep/ sed(seperti yang berdiri sendiri 0x80 byte tidak cocok .), akan memiliki panjang 30 + 1 + 30 + 1 + 2 * 30 = 122 dengan perlatau mawk, 3 * 30 = 90 dengan gawk.

Jika Anda ingin menghitung dalam bentuk byte, perbaiki lokal Cdengan LC_ALL=C grep/awk/sed....

Itu akan memiliki semua 4 solusi mempertimbangkan bahwa baris di atas berisi 122 karakter. Kecuali dalam perldan di alat GNU, Anda masih akan memiliki masalah potensial untuk baris yang berisi karakter NUL (0x0 byte).


¹ perlperilaku dapat dipengaruhi oleh PERL_UNICODEvariabel lingkungan

manatwork
sumber
Apa yang Anda maksud dengan "efisien"?
rowantran
Saya pikir manatwork berarti efisiensi mengetik. awkdapat datang lebih dekat jika Anda drop ($0), yang tersirat;).
Thor
9
BTW, jika Anda meletakkan regexp ke awal baris dengan ^, itu sedikit lebih cepat: misalnya grep '^.\{80\}' file.
cas
4
Solusi perl tidak memperhitungkan pengkodean ukuran variabel seperti UTF-8, tidak seperti semua solusi lainnya.
BatchyX
6
Nilai N yang cukup besar gagal dengan grep tetapi berhasil dengan awk. (mis. grep '^.\{1000\}' filekembali grep: invalid repetition count(s), ketika awk 'length>1000' fileberhasil.)
mdahlman
1

Pendekatan shell:

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

Pendekatan 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

Atau sebagai skrip pendek untuk dibaca:

#!/usr/bin/env python
import sys

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

Jika kita ingin mengecualikan karakter baris baru \ndari perhitungan, kita dapat membuat if len(line) > 79menjadiif len(line.strip()) > 79

Catatan: ini adalah sintaks Python 2.7. Gunakan print()untuk Python 3

Sergiy Kolodyazhnyy
sumber