2009-08-04 28 views
11

[biên tập chèn: Có thể trùng lặp của các poster cùng của earlier question?]bash grep newline

Hi, tôi cần phải trích xuất từ ​​file:

first 
second 
third 

sử dụng lệnh grep, dòng sau :

second 
third 

Lệnh grep sẽ như thế nào?

+0

Bạn có ý nghĩa này hoặc ý của bạn là bạn muốn dòng thứ hai và thứ ba họ có nội dung gì? Ngoài ra, đây có phải là bài tập về nhà của bạn không? – Telemachus

+0

Không phải bài tập về nhà của tôi, chỉ là một nhiệm vụ. Tôi không biết chính xác làm thế nào để xây dựng một biểu thức chính quy ở đây. – Markus

+1

Điều tôi muốn là xây dựng cụm từ thông dụng sẽ chứa ký tự dòng mới. – Markus

Trả lời

1

Dòng? Hoặc dòng?

Hãy thử

grep -E -e '(second|third)' filename 

Edit: grep được dòng định hướng. bạn sẽ phải sử dụng Perl, sed hoặc awk để thực hiện khớp mẫu trên các dòng.

BTW -E nói grep rằng regexp được mở rộng RE.

+0

Đường. Nhưng những gì về việc xây dựng một biểu thức chính quy sẽ được sử dụng bởi egrep? Nhân vật dòng mới được thể hiện như thế nào? – Markus

+0

'egrep 'second \\ nthird' filename' –

0
grep -E '(second|third)' /path/to/file 
egrep -w 'second|third' /path/to/file 
2

Tôi không thực sự hiểu những gì bạn muốn khớp. Tôi sẽ không sử dụng grep, nhưng một trong những điều sau đây:

tail -2 file   # to get last two lines 
head -n +2 file  # to get all but first line 
sed -e '2,3p;d' file # to get lines from second to third 

(không chắc chắn cách tiêu chuẩn đó là, nó hoạt động trong các công cụ GNU cho chắc chắn)

+0

Tôi đồng ý. grep không thực sự là một cách đúng đắn để tiếp tục điều này. – Jim

8

Câu hỏi của bạn trừu tượng "bash grep xuống dòng", ngụ ý rằng bạn muốn khớp với chuỗi ký tự second\nthird - tức là có gì đó chứa dòng mới trong đó.

Kể từ khi grep hoạt động trên "dòng" và hai dòng này là các dòng khác nhau, bạn sẽ không thể khớp theo cách này.

Vì vậy, tôi muốn chia nó thành nhiều nhiệm vụ:

  1. bạn phù hợp với dòng có chứa "thứ hai" và đầu ra dòng mà đã xuất hiện và các dòng tiếp theo:

    grep -A 1 "second" testfile 
    
  2. bạn dịch mỗi dòng mới vào chuỗi được đảm bảo không xảy ra trong đầu vào.Tôi nghĩ rằng cách đơn giản nhất để làm điều đó sẽ được sử dụng perl:

    perl -npe '$x=1-$x; s/\n/##UnUsedSequence##/ if $x;' 
    
  3. bạn làm một grep trên những dòng này, lần này tìm kiếm chuỗi ##UnUsedSequence##third:

    grep "##UnUsedSequence##third" 
    
  4. bạn unwrap các trình tự không sử dụng trở lại vào dòng mới, sed có thể là đơn giản nhất:

    sed -e 's/##UnUsedSequence##/\n' 
    

Vì vậy, lệnh ống kết quả để thực hiện những gì bạn muốn sẽ trông giống như:

grep -A 1 "second" testfile | perl -npe '$x=1-$x; s/\n/##UnUsedSequence##/ if $x;' | grep "##UnUsedSequence##third" | sed -e 's/##UnUsedSequence##/\n/' 

Không phải thanh lịch nhất cho đến nay, nhưng sẽ hoạt động. Tôi tò mò muốn biết cách tiếp cận tốt hơn, mặc dù - có nên có một số.

1

Vì vậy, bạn chỉ không muốn dòng có chứa "đầu tiên"? -v đảo ngược kết quả grep.

$ echo -e "first\nsecond\nthird\n" | grep -v first 
second 
third 
3

Tôi không nghĩ grep là con đường để đi về vấn đề này.

Nếu bạn chỉ muốn tách dòng đầu tiên khỏi bất kỳ tệp nào (để khái quát hóa câu hỏi của bạn), tôi sẽ sử dụng sed thay thế.

sed '1d' INPUT_FILE_NAME 

Điều này sẽ gửi nội dung của tệp đến đầu ra tiêu chuẩn với dòng đầu tiên bị xóa.

Sau đó, bạn có thể chuyển hướng đầu ra tiêu chuẩn sang tệp khác để nắm bắt kết quả.

sed '1d' INPUT_FILE_NAME > OUTPUT_FILE_NAME 

Điều đó sẽ thực hiện.

Nếu bạn phải sử dụng grep và chỉ không muốn để hiển thị phù hợp với đầu tiên vào nó, sau đó thử này:

grep -v first INPUT_FILE_NAME 

Bằng cách vượt qua switch -v, bạn đang nói grep để hiển thị cho bạn mọi thứ nhưng cụm từ mà bạn đang chuyển. Có hiệu lực chỉ cho tôi tất cả mọi thứ nhưng (các) dòng có đầu tiên là trong đó.

Tuy nhiên, nhược điểm là một tệp có nhiều số đầu tiên của sẽ không hiển thị các dòng khác hoặc có thể không phải là hành vi mà bạn đang mong đợi.

Để shunt kết quả vào một tập tin mới, hãy thử này:

grep -v first INPUT_FILE_NAME > OUTPUT_FILE_NAME 

Hope this helps.

+0

Tôi nghĩ rằng bạn có thể có hai ví dụ cuối cùng của bạn về phía sau. – Telemachus

+0

Cảm ơn bạn đã đánh bắt điều đó. – Jim

20

Thay vì grep, bạn có thể sử dụng pcregrep mà hỗ trợ mô hình multiline

pcregrep -M 'second\nthird' file 

-M cho phép mô hình để phù hợp với nhiều hơn một dòng.

+4

Bạn có thể muốn sử dụng '\ s +' thay cho '\ n' tùy thuộc vào kết thúc dòng trong tệp (một số có thể là' \ r \ n') – davemyron

0

bạn có thể sử dụng

$ grep -1 third filename 

này sẽ in một chuỗi với trận đấu và một chuỗi trước và sau. Vì "thứ ba" nằm trong chuỗi cuối cùng, bạn nhận được hai chuỗi cuối cùng.

0

Tôi thích notnoop's answer, nhưng xây dựng trên AndrewY's answer (đó là tốt hơn cho những người không pcregrep, nhưng cách quá phức tạp), bạn chỉ có thể làm:

RESULT=`grep -A1 -s -m1 '^\s*second\s*$' file | grep -s -B1 -m1 '^\s*third\s*$'` 
0
grep -v '^first' filename 

đâu cờ -v đảo ngược trận đấu .

1

grep -A1 "giây" | grep -B1 "third" hoạt động độc đáo và nếu bạn có nhiều kết quả phù hợp, thậm chí nó sẽ loại bỏ dấu phân cách gốc -