2012-02-01 41 views
6

Tôi đã được giao nhiệm vụ với một cái gì đó khá đau đớn và tôi đã tự hỏi nếu có ai có thể giúp đỡ.Tước khối văn bản từ tập tin văn bản lớn

Nhà cung cấp của chúng tôi đã cung cấp tệp mib SNMP (txt). Rất tiếc, rất nhiều tệp này đã lỗi thời và cần được loại bỏ cho ứng dụng giám sát của chúng tôi.

Tôi đã cố gắng làm điều này bằng tay, nhưng nó dài hơn 800.000 dòng, và nó đang phá hỏng ý chí của tôi để sống.

Cấu trúc là một cái gì đó như:

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /* Deprecated from: 600.3              */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 

-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 364.44               */ 
-- /* Deprecated from: 594.3              */ 
-- /*********************************************************************************/ 

Tiếp xúc nhiều lần tại nauseum ngẫu nhiên và quảng cáo

Những gì tôi đang suy nghĩ, là một kịch bản đó sẽ:

tìm dòng chữ "Không được tán thành từ" rồi

delete that line, 
delete the preceding 3 lines, 
delete the following one line, 
delete then all following lines until the next 
"-- /*********************************************************************************/" 

Điều này có hợp lý không? Điều này có thể xảy ra hay tôi chỉ mơ ước?

Thankyou!

+1

Xóa từ 'Deprecated' đến'/** ... 'là khá dễ dàng, xóa 3 dòng trước đó có phần khó khăn hơn. – Kevin

+0

Tôi nghĩ rằng việc xử lý điều này với sed hoặc awk sẽ sap _my_ sẽ sống. Perl hoặc một số ngôn ngữ khác cho phép bạn phân tích xung quanh ranh giới đường thẳng là một lựa chọn tốt hơn cho vấn đề này. –

Trả lời

3

Chỉnh sửa: Tôi vừa mới nhận ra rằng tôi đã đọc sai câu hỏi của bạn, ngay cả sau khi đã được upvoted một vài lần. Câu trả lời của tôi trước đây đã tắt! Bây giờ phải chính xác hơn, nhưng với một số giả định bổ sung. Giải pháp đơn giản chỉ có thể giúp bạn có được cho đến nay!

này có thể có thể giúp bạn ra ngoài, với một vài giả định:

cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } 1' 

Lệnh cat chỉ đơn giản là đó để bóp ra dòng mới dư thừa, vì vậy awk có thể hoạt động dễ dàng hơn. Đối với awk, số -vFS='\n' cho biết rằng các trường được phân cách bằng dòng mới và -vRS='\n\n' cho biết rằng các bản ghi được phân tách bằng hai dòng mới liên tiếp. Sau đó, /Deprecated from/ tìm các bản ghi có văn bản đó và { getline; next } đọc trong hồ sơ tiếp theo sau đó và khiến nó di chuyển. 1 là phím tắt để in các dòng đạt đến điểm sau.

Điều này sẽ đảm nhận sau:

  • Tất cả các bình luận và văn bản khối được tách ra bởi ít nhất một dòng trống ở hai bên
  • Chỉ có khối bình luận và khối văn bản xen kẽ đều
  • Không có dòng trống trong khối văn bản

Vì vậy, nó có thể không hoàn toàn phù hợp với bạn. Nếu những giả định này không sao, nó sẽ làm cho awk trở thành lựa chọn tốt cho công việc này, như bạn có thể thấy: kịch bản rất nhỏ!

$ cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } 1' 
-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 
Some text 
some text 
Some text 

Ngoài ra, như bạn có thể thấy, các dòng mới vẫn bị đẩy ra ngoài.Để hỗ trợ điều này, bạn có thể sửa đổi lệnh như sau:

$ cat -s data | awk -vFS='\n' -vRS='\n\n' '/Deprecated from/ { getline; next } { printf "%s\n\n", $0 }' 
-- /*********************************************************************************/ 
-- /* MIB table for Hardware              */ 
-- /* Valid from: 543.44               */ 
-- /*********************************************************************************/ 

Some text 
some text 
Some text 
1

Đây là một macro đơn giản vim.

  1. Mang lên tập tin: $ vim filename
  2. Nhấn q a để ghi vĩ mô trong sổ đăng ký a
  3. Loại /Deprecated from: sau đó ấn Enter (để tìm kiếm văn bản)
  4. 3k (đi lên 3 lines)
  5. 4dd (xóa dòng này và 3 tiếp theo)
  6. d/\*\*\*\*\*\* (để xóa các dòng lên đến biểu tượng)
  7. (nếu cần thiết) báo chí dd (xóa dòng hiện tại)
  8. Nhấn q để kết thúc ghi hình vĩ mô

  9. Loại [email protected] (để thực hiện vĩ mô một triệu lần)

1

tôi rất đồng ý với nhận xét về việc sử dụng ngôn ngữ kịch bản khác để giải quyết vấn đề này. Ruby, Perl, hoặc Python có thể sẽ tốt hơn. Nhưng để giải trí, đây là một kịch bản Awk xấu xí làm điều đó. Các trận đấu có thể có thể sử dụng một số công việc nếu họ không thích hợp. Nhưng thực hiện một máy trạng thái đơn giản. Nó theo dõi nếu nó đang ở trong một tiêu đề hay không và xác định nếu nó không được chấp nhận. Nó lưu trữ các dòng tiêu đề trong một mảng. Khi nó đến cuối tiêu đề, nó sẽ in đầu trang (nếu không được dùng nữa). Khi không có trong một tiêu đề, nó sẽ in các dòng nếu phần trước không bị phản đối.

{ 
    if ($0 ~ /-- \/\**+\//) { 
     # This matches one of the -- /*********...****/ lines 
     if (headercount > 0) { 
     # this must be the closing line in the header 
     if (!deprecated) { 
      for (i = 0; i < headercount; i++) { 
       print headers[i] 
      } 
      # print closing line 
      print 
     } # if not deprecated 

     headercount = 0 
     } 
     else { 
     # must be starting a new section 
     headers[0] = $0 
     headercount = 1 
     deprecated = 0 
     } 
    } 
    else { 
     if (headercount == 0) { 
     # not in a header section - print if not deprecated 
     if (!deprecated) { 
      print 
     } 
     } 
     else { 
     # in a header section - track if it is a deprecated section 
     if ($0 ~ /Deprecated from/) { 
      deprecated = 1 
     } 
     # store the header info to dump when we hit the end 
     headers[headercount++] = $0; 
     } 

    } 
} 
2

Điều này có thể làm việc cho bạn:

sed '$!N;$!N;:a;$q;N;/Deprecated from/!{P;s/^[^\n]*\n//;ba};$d;$!N;$d;s/.*//;:b;$d;N;/^\n-- \/\*\+\/$/!{s/.*//;bb};D' file 

Dưới đây là một giải pháp nhẹ dễ dàng hơn (kém hiệu quả vì nó mất 2 đèo):

awk '/Deprecated from/{a=NR-3;getline;next};a>0 && /^-- \/\*+\/$/{b=NR-1;print a "," b "d";a=b=0};END{if(a>0)print a ",$d"}' file | 
sed -f - file 
+0

Tôi rất muốn làm việc đó, nhưng nó không dành cho tôi. Tôi không in được gì cả. –

+0

@DanFego Rất tiếc! để lại một trợ giúp gỡ lỗi. Đã xóa nó, hãy thử lại. – potong

+1

Đó là một đống lộn xộn của các chữ cái và ký hiệu, nhưng nó hoạt động cho tôi! –

Các vấn đề liên quan