Xóa các dòng không có nhiều hơn hoặc ít hơn các trường 'N'?


9

Tôi đang làm việc trên mac với sed, perl, awk, bash ..

Tôi có một tệp văn bản lớn (10 GB) có 13 trường (cột) TABdữ liệu được phân tách. Thật không may, một số dòng này không liên quan TABs, vì vậy tôi muốn xóa toàn bộ dòng nơi chúng ta có thêm các trường TABs và do đó các trường không bằng nhau. (Tôi không ngại loại bỏ toàn bộ các dòng)

Những gì tôi hiện đang ghi số lượng các trường vào một tập tin khác.

awk -F'\t' '{print NF}' infile  > fieldCount

head fieldCount
13
13
10
13
13
13
14
13
13
13

Tôi muốn xây dựng một tập lệnh ngắn loại bỏ bất kỳ dòng nào có nhiều hơn (hoặc ít hơn) hơn 13 trường thích hợp (từ tệp gốc).

  1. tốc độ là hữu ích vì tôi phải làm điều này trên nhiều tập tin
  2. làm điều đó trong một lần quét sẽ rất tuyệt
  3. Tôi hiện đang chuyển tệp fieldCount sang Python, cố gắng tải từng dòng một.

BIÊN TẬP:

vaild (13 cột)

a       b       c       d       e       f       g       h       i       j       k       l       m

không hợp lệ (14 cột)

a       b       c       d       e       f       g       h       i       j       k       l       m       n

Bạn có thể cho ví dụ dòng hợp lệ và dòng không hợp lệ?
cuonglm

Câu trả lời:


11

Bạn gần như đã có nó rồi:

awk -F '\ t' 'NF == 13 {print}' infile   > newfile

Và, nếu bạn đang sử dụng một trong những hệ thống mà bạn bị tính năng nhấn phím (:)), bạn có thể rút ngắn điều đó thành

awk -F '\ t' 'NF == 13' infile   > newfile

Để thực hiện nhiều tệp trong một lần quét và thực sự thay đổi các tệp (và không chỉ tạo tệp mới), hãy xác định tên tệp không được sử dụng (ví dụ scharf:) và thực hiện một vòng lặp, như sau:

cho f trong danh sách
làm
    awk -F '\ t' 'NF == 13 {print}' "$ f"> scharf && mv -f - scharf "$ f"
làm xong

listthể là một hoặc nhiều tên tệp và / hoặc các mẫu mở rộng tên tệp ký tự đại diện; ví dụ,

cho f trong blue.data green.data * .dat cam.data red.data /ultra/violet.dat

Các mvlệnh ghi đè các tập tin đầu vào (ví dụ blue.data) với tạm thời scharftập tin (trong đó có duy nhất các dòng từ tập tin đầu vào với 13 lĩnh vực). (Hãy chắc chắn đây là những gì bạn muốn làm, và hãy cẩn thận. Để an toàn, có lẽ bạn nên sao lưu dữ liệu của bạn đầu tiên.) Các -fkể mvđể ghi đè lên tập tin đầu vào, mặc dù nó đã tồn tại. Việc --bảo vệ bạn chống lại sự kỳ lạ nếu bất kỳ tệp nào của bạn có tên bắt đầu bằng -.


chỉ cần một cú đẩy nhẹ là tất cả những gì tôi cần
T. Scharf

2

Vì đây là một tệp lớn, nên có thể sử dụng một công cụ phức tạp hơn một chút để tăng hiệu suất. Thông thường, các công cụ chuyên dụng nhanh hơn các công cụ tổng quát. Ví dụ, giải quyết cùng một vấn đề có cutxu hướng nhanh hơn so với grepxu hướng nhanh hơn so với sedxu hướng nhanh hơn awk(mặt trái là các công cụ sau này có thể làm những việc mà trước đây không thể làm được).

Bạn muốn xóa các dòng có 13 ký tự tab trở lên, vì vậy:

LC_ALL=C grep -Ev '(␉.*){13}'

hoặc có thể (tôi không mong đợi một sự khác biệt hiệu suất có thể đo lường được)

LC_ALL=C grep -Ev '(␉.*){12}␉'

nơi là một ký tự tab chữ. Đặt ngôn ngữ Clà không cần thiết, nhưng tăng tốc một số phiên bản GNU grep so với các ngôn ngữ đa nhân.


1

Với perl:

perl -F'\t' -anle 'print if @F == 13' file

để chỉnh sửa tại chỗ, thêm -itùy chọn:

perl -i.bak -F'\t' -anle 'print if @F == 13' file

cảm ơn Gnouc - Tôi phải chấp nhận câu trả lời của G-mans anh ấy đã đánh bại bạn trong vài phút .. nhưng tôi thực sự đánh giá cao nó
T. Scharf

@ T.Scharf: Tôi nghĩ của tôi là tốt hơn nếu bạn muốn làm với nhiều tệp. Nhưng đừng bận tâm chọn điều gì là tốt nhất cho bạn.
cuonglm
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.