Lệnh shell Linux để lọc tệp văn bản theo độ dài dòng


19

Tôi có một hình ảnh đĩa 30gb của một phân vùng borked (nghĩ dd if=/dev/sda1 of=diskimage) mà tôi cần khôi phục một số tệp văn bản từ. Các công cụ khắc dữ liệu như foremostchỉ hoạt động trên các tệp có tiêu đề được xác định rõ, tức là không phải tệp văn bản thuần túy, vì vậy tôi đã dựa vào người bạn tốt của mình strings.

strings diskimage > diskstrings.txt đã tạo ra một tệp văn bản 3gb chứa một chuỗi các chuỗi, chủ yếu là những thứ vô dụng, trộn lẫn với văn bản mà tôi thực sự muốn.

Hầu hết các tàu tuần dương có xu hướng thực sự dài, chuỗi liên tục vô nghĩa. Nội dung tôi quan tâm được đảm bảo dưới 16kb, vì vậy tôi sẽ lọc tệp theo độ dài dòng. Đây là tập lệnh Python tôi đang sử dụng để làm như vậy:

infile  = open ("infile.txt" ,"r");
outfile = open ("outfile.txt","w");
for line in infile:
    if len(line) < 16384:
        outfile.write(line)
infile.close()
outfile.close()

Điều này hoạt động, nhưng để tham khảo trong tương lai: Có bất kỳ câu thần chú một dòng ma thuật nào (nghĩ awk, sed) sẽ lọc một tệp theo độ dài dòng không?

Câu trả lời:


28
awk '{ if (length($0) < 16384) print }' yourfile >your_output_file.txt

sẽ in các dòng ngắn hơn 16 kilobyte, như trong ví dụ của riêng bạn.

Hoặc nếu bạn thích Perl:

perl -nle 'if (length($_) < 16384) { print }' yourfile >your_output_file.txt

Chà, thật đơn giản. Cảm ơn bạn. :)
Li-aung Yip

Đã thêm phiên bản Perl :-)
Janne Pikkarainen

Và tập lệnh awk có thể được viết dưới dạng awk 'length($0) < 16384' file > output, vì hành động mặc định là in dòng.
glenn jackman

8

Điều này tương tự như câu trả lời của Ansgar, nhưng nhanh hơn một chút trong các thử nghiệm của tôi:

awk 'length($0) < 16384' infile >outfile

Đó là tốc độ tương tự như các câu trả lời awk khác. Nó dựa vào ẩn ý printcủa một biểu thức thực sự, nhưng không cần phải dành thời gian để phân chia dòng như Ansgar.

Lưu ý rằng AWK cung cấp cho bạn ifmiễn phí. Lệnh trên tương đương với:

awk 'length($0) < 16384 {print}' infile >outfile

Không có ifcâu trả lời rõ ràng (hoặc tập hợp các dấu ngoặc nhọn xung quanh) như trong một số câu trả lời khác.

Đây là một cách để làm điều đó trong sed:

sed '/.\{16384\}/d' infile >outfile

hoặc là:

sed -r '/.{16384}/d' infile >outfile

xóa bất kỳ dòng nào chứa 16384 (hoặc nhiều hơn) ký tự.

Để hoàn thiện, đây là cách bạn sử dụng sedđể lưu các dòng dài hơn ngưỡng của bạn:

sed '/^.\{0,16383\}$/d' infile >outfile

2

Bạn có thể awknhư:

$ awk '{ if (length($0) < 16384) { print } }' /path/to/text/file

Điều này sẽ in các dòng dài hơn 16K ký tự (16 * 1024).

Bạn cũng có thể sử dụng grep:

$ grep ".\{,16384\}" /path/to/text/file

Điều này sẽ in các dòng nhiều nhất là 16K ký tự.


Không chắc chắn greplà một ý tưởng tốt như vậy - đó là một biểu thức chính quy đơn giản, chắc chắn, nhưng đắt hơn về mặt tính toán awk. "Một người đàn ông có vấn đề nói" Tôi sẽ sử dụng các biểu thức thông thường! "Bây giờ anh ta có hai vấn đề." ;)
Li-aung Yip

Nó chỉ là một cách khác để làm điều đó. Tùy chọn đầu tiên tôi đăng là sử dụng awk.
Khaled

1
1 cho regexp, bởi vì nó Tất chơi gôn tốt hơn, và nó không làm cho tôi đọc awk man =)
Ciro Santilli新疆改造中心法轮功六四事件

2

Không thực sự khác với các câu trả lời đã được đưa ra, nhưng vẫn ngắn hơn:

awk -F '' 'NF < 16384' infile >outfile
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.