2009-12-22 8 views
8

Làm cách nào để hiển thị dữ liệu từ đầu tệp cho đến khi xuất hiện cụm từ thông dụng đầu tiên?Làm cách nào để hiển thị dữ liệu từ đầu tệp cho đến lần xuất hiện đầu tiên của cụm từ thông dụng?

Ví dụ, nếu tôi có một tập tin có chứa:

One 
Two 
Three 
Bravo 
Four 
Five 

Tôi muốn bắt đầu hiển thị các nội dung của tập tin bắt đầu từ dòng 1 và dừng khi tôi tìm chuỗi "B *". Vì vậy, đầu ra sẽ trông như thế này:

One 
Two 
Three 

Trả lời

2

trong Perl:

perl -nle '/B.*/ && last; print; ' source.txt 
+0

/B.*/ sẽ phù hợp với bất cứ điều gì có chứa một B, chứ không phải bắt đầu với một B. – rjh

+0

Câu hỏi không nói rằng 'B' phải ở đầu dòng. –

+0

Xin lỗi, bạn nói đúng - tùy thuộc vào cách diễn giải của chúng tôi ở đó. – rjh

5
sed '/^B/,$d' 

đọc mà như sau: Xóa (d) tất cả các dòng bắt đầu với dòng đầu tiên bắt đầu với một "B "(/^B/), lên và cho đến dòng cuối cùng ($).

0

Nếu Perl là một possibilty, bạn có thể làm một cái gì đó như thế này:

% perl -0ne 'if (/B.*/) { print $`; last }' INPUT_FILE 
+0

Dường như đọc quá nhiều tập tin vào bộ nhớ trước khi làm bất cứ điều gì. – ephemient

7

nếu nó từ khi bắt đầu của tập tin

awk '/^B/{exit}1' file 

nếu bạn muốn bắt đầu từ dòng số cụ thể

awk '/^B/{exit}NR>=10' file # start from line 10 
11

perl -pe 'last if /^B/' source.txt

Giải thích: công tắc -p thêm một vòng xung quanh mã, biến nó thành này:

 
while (<>) { 
    last if /^B.*/; # The bit we provide 
    print; 
} 

Từ khóa cuối cùng ra khỏi vòng lặp xung quanh ngay lập tức nếu tình trạng nắm giữ - trong trường hợp này,/^ B /, cho biết dòng bắt đầu bằng chữ B.

6
sed -n '1,/^B/p' 

In từ dòng 1 đến/^ B/(bao gồm). -n triệt tiêu tiếng vang mặc định.


Cập nhật: Opps ....không muốn "Bravo", do đó thay vì các hành động ngược lại là cần thiết ;-)

sed -n '/^B/,$!p' 

/I3az/

+0

Thật không may, bản in này bao gồm cả dòng "Bravo", trong khi câu hỏi muốn loại trừ dòng "Bravo". – ndim

+0

Arghh! ... không đọc chính xác câu hỏi. Cập nhật với hành động ngược lại "! P" (ví dụ: in!) Cho mọi thứ không nằm trong khoảng/^ B/và kết thúc tệp. Rất cám ơn vì đã phát hiện ra điều này. – draegtun

+0

Ah. '!' sửa đổi một dải địa chỉ sao cho nó chỉ khớp với địa chỉ mà nó không khớp, và ngược lại. Nó vẫn là một phần của dải địa chỉ. Vâng, '!' Là mới đối với tôi ... cảm ơn vì đã chỉ cho tôi. – ndim

1

Đây là một perl one-liner:

perl -pe 'last if /B/' file 
2

Chỉ cần chia sẻ một số tôi đã nhận được:

Dữ liệu in bắt đầu từ dòng đầu tiên và tiếp tục cho đến khi chúng tôi tìm thấy kết quả phù hợp với regex, sau đó dừng lại:

<command> | perl -n -e 'print "$_" if 1 ... /<regex>/;' 

dữ liệu In bắt đầu từ dòng đầu tiên, và tiếp tục cho đến khi chúng ta tìm thấy một trận đấu để regex, NHƯNG không hiển thị dòng phù hợp với biểu thức chính quy:

<command> | perl -pe '/<regex>/ && exit;' 

Làm nó trong sed:

<command> | sed -n '1,/<regex>/p' 
+0

Toán tử flip flop là một trong những mục yêu thích của tôi và tình huống này là một trong số ít lần tôi sử dụng nó. :) –

3

Một số lệnh sed do người khác cung cấp sẽ tiếp tục xử lý không cần thiết đầu vào sau khi tìm thấy regex có thể khá chậm đối với đầu vào lớn. Đây bỏ khi regex được tìm thấy:

sed -n '/^Bravo/q;p' 
2

Vấn đề của bạn là một biến thể của một câu trả lời trong perlfaq6: How can I pull out lines between two patterns that are themselves on different lines?.


Bạn có thể sử dụng Perl của hơi kỳ lạ .. điều hành (ghi nhận ở perlop):

perl -ne 'print if /START/ .. /END/' file1 file2 ... 

Nếu bạn muốn dòng văn bản và không, bạn sẽ sử dụng

perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ... 

Nhưng nếu bạn muốn các lần xuất hiện lồng nhau của START qua END, bạn sẽ chạy lên chống lại vấn đề được mô tả trong câu hỏi trong phần này về kết hợp văn bản cân bằng.

Dưới đây là một ví dụ khác của việc sử dụng ..:

while (<>) { 
    $in_header = 1 .. /^$/; 
    $in_body = /^$/ .. eof; 
# now choose between them 
} continue { 
    $. = 0 if eof; # fix $. 
} 
0

lót với các lệnh shell cơ bản:

head -`grep -n B file|head -1|cut -f1 -d":"` file