Tìm bất kỳ dòng nào vượt quá độ dài nhất định


Câu trả lời:


90

Theo thứ tự giảm tốc độ (trên hệ thống GNU trong ngôn ngữ UTF-8 và trên đầu vào ASCII) theo các thử nghiệm của tôi:

grep '.\{80\}' file

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

awk 'length>79' file

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

Ngoại trừ perl¹ một (hoặc cho awk/ grep/ sedtriển khai (như mawkhoặc busybox) không hỗ trợ các ký tự nhiều byte), tính chiều dài tính theo số lượng ký tự (theo LC_CTYPEcài đặt của miền địa phương) thay vì byte .

Nếu có các byte trong đầu vào không tạo thành một phần của các ký tự hợp lệ (đôi khi xảy ra khi bộ ký tự của miền địa phương là UTF-8 và đầu vào ở dạng mã hóa khác nhau), thì tùy thuộc vào cách triển khai giải pháp và công cụ, các byte đó sẽ được tính là 1 ký tự hoặc 0 hoặc không khớp ..

Chẳng hạn, một dòng bao gồm 30 asa 0x80 byte, 30 bgiây, 0x81 byte và 30 UTF-8 és (được mã hóa thành 0xc3 0xa9), trong ngôn ngữ UTF-8 sẽ không khớp .\{80\}với GNU grep/ sed(vì đó là 0x80 byte độc ​​lập không khớp .), sẽ có độ dài 30 + 1 + 30 + 1 + 2 * 30 = 122 với perlhoặc mawk, 3 * 30 = 90 với gawk.

Nếu bạn muốn tính theo byte, hãy sửa miền địa phương Cvới LC_ALL=C grep/awk/sed....

Điều đó sẽ có tất cả 4 giải pháp xem xét dòng trên chứa 122 ký tự. Ngoại trừ perlcác công cụ GNU và, bạn vẫn có các vấn đề tiềm ẩn đối với các dòng có chứa các ký tự NUL (0x0 byte).


Behavior perlhành vi có thể bị ảnh hưởng bởi PERL_UNICODEbiến môi trường


Bạn có ý nghĩa gì bởi "hiệu quả"?
Rowantran

Tôi nghĩ rằng manatwork có nghĩa là gõ hiệu quả. awkcó thể đến gần hơn nếu bạn thả ($0), dù sao thì nó cũng tiềm ẩn;).
Thor

9
BTW, nếu bạn neo regrec vào đầu dòng ^, nó sẽ nhanh hơn một chút: vd grep '^.\{80\}' file.
cas

4
Giải pháp perl không tính đến mã hóa kích thước thay đổi, chẳng hạn như UTF-8, không giống như tất cả các giải pháp khác.
BatchyX

6
Đủ các giá trị lớn của N thất bại với grep nhưng thành công với awk. (ví dụ grep '^.\{1000\}' filetrả về grep: invalid repetition count(s), trong khi awk 'length>1000' filethành công.)
mdahlman

1

Cách tiếp cận Shell:

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

Cách tiếp cận 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

Hoặc như một đoạn script ngắn để dễ đọc:

#!/usr/bin/env python
import sys

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

Nếu chúng ta muốn loại trừ ký tự xuống dòng \ntừ tính toán, chúng ta có thể làm if len(line) > 79đượcif len(line.strip()) > 79

Lưu ý bên lề: đây là cú pháp Python 2.7. Sử dụng print()cho Python 3

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.