2013-08-10 76 views
25

Hi Tôi có một tập tin chứa một danh sách các url, trông giống như dưới đây:grep + A: in tất cả mọi thứ sau khi trận đấu

file1:

http://www.google.com 
http://www.bing.com 
http://www.yahoo.com 
http://www.baidu.com 
http://www.yandex.com 
.... 

Tôi muốn có được tất cả các hồ sơ sau: http://www.yahoo.com, kết quả trông giống như dưới đây:

file2:

http://www.baidu.com 
http://www.yandex.com 
.... 

tôi biết rằng tôi có thể sử dụng grep để tìm ra số dòng nơi yahoo.com đang sử dụng

$grep -n 'http://www.yahoo.com' file1 
3 http://www.yahoo.com 

Nhưng tôi không biết cách lấy tệp sau số dòng 3. Ngoài ra, tôi biết có một lá cờ trong grep -A in các dòng sau trận đấu của bạn . Tuy nhiên, bạn cần xác định số lượng dòng bạn muốn sau trận đấu. Tôi tự hỏi là có một cái gì đó để có được xung quanh vấn đề đó. Giống như:

PSEUDO CODE: 
$ grep -n 'http://www.yahoo.com' -A all file1 > file2 

Tôi biết chúng tôi có thể sử dụng số dòng tôi nhận và wc -l để nhận được số dòng sau yahoo.com, tuy nhiên .. cảm thấy khá lame.

Mong được một giải pháp tiện dụng và dễ dàng. Hãy tự do chỉ trích tôi vì đã làm phức tạp vấn đề ngay từ đầu và các lệnh awk và sed cũng được hoan nghênh!

Trả lời

37

AWK

Nếu bạn không nhớ sử dụng awk:

awk '/yahoo/{y=1;next}y' data.txt 

Kịch bản này có hai phần:

/yahoo/ { y = 1; next } 
y 

Phần đầu tiên nói rằng nếu chúng ta gặp phải một phù hợp với yahoo, chúng tôi đặt biến y = 1, sau đó bỏ qua dòng đó (lệnh next sẽ chuyển sang dòng tiếp theo, do đó bỏ qua bất kỳ quy trình nào khác ing trên dòng hiện tại). Nếu không có lệnh next, dòng yahoo sẽ được in.

Phần thứ hai là một tay viết tắt của:

y != 0 { print } 

Có nghĩa là, đối với mỗi dòng, nếu biến y là không, chúng tôi in dòng đó. Trong awk, nếu bạn tham khảo một biến, biến đó sẽ được tạo ra và là số không hoặc chuỗi rỗng, tùy thuộc vào ngữ cảnh. Trước khi gặp phải yahoo, biến y là 0, vì vậy tập lệnh không in bất kỳ thứ gì. Sau khi gặp yahoo, y là 1, vì vậy mọi dòng sau đó sẽ được in.

Sed

Hoặc, sử dụng sed, sau đây sẽ xóa tất cả mọi thứ lên đến và bao gồm cả phù hợp với yahoo:

sed '1,/yahoo/d' data.txt 
+0

bạn có thể giải thích cú pháp awk một chút không? Hiểu biết của tôi: /yahoo/tìm kiếm dòng sử dụng cụm từ thông dụng, sau đó từ dòng đó, tạo biến có tên là y và sau đó đặt giá trị là 1, sau đó nếu dòng được in phụ thuộc vào giá trị của y. Sau đó, mọi dòng sẽ được in sau yahoo. Tôi không hoàn toàn chắc chắn về lệnh "tiếp theo" –

+0

Tệ của tôi, tôi đã quên giải thích. Vui lòng xem cập nhật của tôi. –

+0

Nếu tôi hiểu nó một cách chính xác nó nên đọc như thế này: y = 0 cho dòng trong file: if (/ yahoo /): y = 1 đi đến dòng tiếp theo if (y ! = 1): dòng in –

12

Việc này dễ thực hiện hơn nhiều với sed hơn grep. sed có thể áp dụng bất kỳ lệnh một chữ cái nào của nó cho một phạm vi bao gồm các dòng; cú pháp chung cho điều này là

START , STOP COMMAND 

ngoại trừ không có bất kỳ dấu cách nào. STARTSTOP mỗi người có thể là một số (có nghĩa là "số dòng N", bắt đầu từ 1); một ký hiệu đô la (có nghĩa là "phần cuối của tệp"), hoặc một regexp kèm theo dấu gạch chéo, có nghĩa là "dòng đầu tiên khớp với regexp này". (Các quy tắc chính xác là hơi phức tạp hơn; the GNU sed manual has more detail.)

Vì vậy, bạn có thể làm những gì bạn muốn như vậy:

sed -n -e '/http:\/\/www\.yahoo\.com/,$p' file1 > file2 

Các -n có nghĩa là "không in bất cứ điều gì trừ khi được nói tới", và chỉ thị -e có nghĩa là "từ lần xuất hiện đầu tiên của một dòng khớp với regexp /http:\/\/www\.yahoo\.com/ vào cuối tệp, p rint".

Điều này sẽ bao gồm dòng có http://www.yahoo.com/ trên đầu ra. Nếu bạn muốn tất cả mọi thứ sau thời điểm đó nhưng không phải là dòng chính, cách dễ nhất để làm điều đó là để đảo ngược hoạt động:

sed -e '1,/http:\/\/www\.yahoo\.com/d' file1 > file2 

có nghĩa là "cho dòng 1 đến dòng đầu tiên phù hợp với regexp /http:\/\/www\.yahoo\.com/, d elete sự dòng "(và sau đó, ngầm, in mọi thứ khác; lưu ý rằng -nkhông phải là đã sử dụng thời gian này).

+0

$ p là gì? Được rồi, đó là STOP. Khi nào nó dừng lại? Tìm kiếm trên google không tiết lộ gì cả. Các hướng dẫn sed tôi đã xem xét không đề cập đến nó. – 7stud

+0

@ 7stud Trong điều khoản tôi đã sử dụng, STOP chỉ là ký hiệu đô la; 'p' là COMMAND. ''/.../,$'' có nghĩa là "làm điều gì đó bắt đầu với dòng đầu tiên khớp với cụm từ thông dụng và tiếp tục cho đến khi kết thúc tệp", và 'p' có nghĩa là 'in'. http://www.gnu.org/software/sed/manual/html_node/Addresses.html có thể hữu ích. – zwol

+1

* 'p' là COMMAND * - Ahh. Tại sao không viết nó như là: '/../,$ p?' Cho rõ ràng, với định dạng là 'START, STOP COMMAND'? – 7stud

3

này được dễ dàng nhất thực hiện trong Perl:

perl -ne 'print unless 1 .. m(http://www\.yahoo\.com)' file 

Nói cách khác, in tất cả các dòng không phải là giữa dòng 1 và lần xuất hiện đầu tiên của mẫu đó.

+0

cũng hoạt động. Không bao giờ sử dụng Perl trước. 1 .. m (tìm kiếm) có nghĩa là gì, cú pháp trông khác với các ngôn ngữ lập trình khác. Không khá thẳng về phía trước .. –

+0

@ user84771 Nó có nghĩa là từ khi số dòng hiện tại là thông qua một dòng phù hợp với tìm kiếm đó. Thông thường, tìm kiếm bằng '/ search /' nhưng tôi không muốn thoát khỏi dấu gạch chéo. Ví dụ: bạn có thể nói 'in if 1 ../^ $/'để in qua và bao gồm một dòng trống. – tchrist

+1

Đối với những người vẫn còn tìm thấy bí mật một lớp lót này, khóa là toán tử phạm vi (dấu chấm kép). Trong bối cảnh vô hướng, toán tử phạm vi hoạt động như một flip-flop duy trì trạng thái boolean của riêng nó. Ngoài ra, khi một trong các toán hạng của nó là một hằng số (như "1" ở trên), nó khớp với số dòng hiện tại của đầu vào đang được đánh giá. Chi tiết tại đây: http://perldoc.perl.org/perlop.html#Range-Operators – billyw

2

sử dụng kịch bản

#get index of yahoo word 
index=`grep -n "yahoo" filepath | cut -d':' -f1` 
#get total number of lines in file 
totallines=`wc -l filepath | cut -d' ' -f1` 
#subtract totallines with index 
result=`expr $total - $index` 
#gives the desired output 
grep -A $result "yahoo" filepath 
+0

Tại sao bạn lại phát minh ra một lớp lót cơ bản là gì? – tripleee

+4

chỉ đang cố gắng trả lời câu hỏi grep với câu trả lời grep. – user1502952

+0

đó là rất hữu ích user1502952 .. cảm ơn rất nhiều! nhưng có vẻ như lần sau tôi có một truy vấn đặc biệt, tôi sẽ đi với sed hoặc awk :) –

5
awk '/yahoo/ ? c++ : c' file1 

Hoặc golfed

awk '/yahoo/?c++:c' file1 

quả

 
http://www.baidu.com 
http://www.yandex.com