2012-04-26 31 views
9

Có lẽ đây là một câu hỏi rất cơ bản đối với các lập trình viên vỏ. Nhưng giả sử tôi có tệp văn bản A và B và B là một tập con của A.lập trình vỏ cơ bản

Tôi muốn tạo tệp văn bản C chứa dữ liệu (A-B).

Vì vậy hãy bỏ qua tất cả các dòng chung.

Dòng trong các tập tin là dữ liệu số: như

id , some aspect, other aspec. 

Cảm ơn.

+0

Bạn chưa đề cập, một trong hai cách, có hoặc không dữ liệu của bạn có thể chứa dòng trùng lặp. Nếu có thể, hãy lưu ý rằng phương thức 'sort' +' uniq' của Tim Pote ** không hoạt động ** khi có các dòng trùng lặp chưa được so khớp trong 'A'. Các phương thức 'awk' và' comm' làm việc với các bản sao trong 'A'. –

Trả lời

12

Sử dụng sortuniq

sort a b | uniq -u 

Nếu bạn muốn các dòng giống nhau giữa A và B, bạn có thể sử dụng uniq -d

sort a b | uniq -d 

này giả định tất nhiên rằng các dữ liệu trong A và B là chính xác là giống nhau. Không thể mất bất kỳ dấu cách hoặc tab nào trong bộ dữ liệu. Nếu có, bạn sẽ phải dọn sạch dữ liệu với số sed, tr hoặc trước tiên là awk.

Sửa

Như Peter. O đã chỉ ra, điều này sẽ không thành công nếu xảy ra trùng lặp chính xác trong tệp a. Nếu đó là vấn đề, bạn có thể khắc phục sự cố bằng cách thực hiện việc này:

sort <(sort -u a) b | uniq -u 
+0

một câu hỏi rất ngây thơ. Làm thế nào để lưu nó trong tập tin "c" ?? – Fraz

+1

Bạn cần chuyển hướng đầu ra bằng '>'.Vì vậy, lệnh sau đó sẽ là: 'sort a b | uniq -u> c' –

+1

'sắp xếp a | uniq -u> c' – dpp

4

Một cách sử dụng awk. Chuyển hướng để lưu nội dung trong bất kỳ tệp nào thay vì STDOUT.

awk 'FNR == NR { data[ $0 ] = 1; next } FNR < NR { if ($0 in data) { next } print $0 }' fileB fileA 

CẬP NHẬT với một lệnh hiệu quả hơn. Nhờ Peter.O:

awk 'FNR==NR{data[$0]; next}; $0 in data{next}; 1' fileB fileA 
+0

Chỉ cần một vài điểm để làm cho nó nhiều hơn một chút consise (và nhanh hơn): 1) Bạn không cần phải gán một giá trị cho mảng; chỉ đề cập đến nó tạo ra phần chỉ mục. 2) Kiểm tra FNR thứ hai là không cần thiết, như trước 'next' phục vụ cho điều đó. 3) Kiểm thử 'if' là thừa, vì' $ 0 trong dữ liệu' là một thử nghiệm theo đúng nghĩa của nó. 4) Bất kỳ giá trị khác 0 sẽ gây ra '$ 0' để in, vì vậy' print $ 0' có thể là "giá trị boolean": 'awk 'FNR == NR {data [$ 0]; kế tiếp}; $ 0 trong dữ liệu {next}; 1 'fileB fileA' –

+0

@ Peter.O: Cảm ơn bạn đã đề xuất. Tôi thêm lệnh của bạn vào câu trả lời. – Birei

+0

Bạn cũng không cần những câu lệnh rỗng (dấu chấm phẩy) và thay vì kiểm tra $ 0 trong dữ liệu và thực hiện tiếp theo và sau đó có một bản in ẩn sau đó, bạn có thể phủ nhận thử nghiệm, và bạn không cần tiếp theo (trừ khi fileB là rất lớn và hiệu quả là một vấn đề) vì vậy bạn chỉ có thể viết nó là 'awk' FNR == NR {data [$ 0]}! ($ 0 trong dữ liệu} 'fileB fileA'. –

7

Có một tiện ích gọi là comm đó là sử dụng cho chỉ này:

comm -23 A B > C 

nơi -2 có nghĩa là "từ chối dòng duy nhất để nộp B" (bạn nói có aren 't bất kỳ), và -3 có nghĩa là "từ chối các dòng phổ biến cho cả hai tập tin".

@BartonChittenden làm cho một điểm tốt:

comm -23 <(sort A) <(sort B) > C 
+2

Lưu ý rằng cả hai tập tin phải –

+0

+1 để hiển thị cho tôi 'dấu phẩy, mà tôi chưa bao giờ nghe đến. +10 để chỉ cho tôi' <(lệnh) 'mà tôi chưa bao giờ nghe đến. –

+1

Đó được gọi là" thay thế tiến trình "và cho phép bạn xử lý đầu ra của một lệnh như thể nó là một tập tin. –

2
awk 'FNR==NR{a[$0];next}(!($0 in a))' B A 
Các vấn đề liên quan