Chỉ in đầu ra sau khi tìm thấy mẫu


13

Có một kịch bản (hãy gọi nó echoer) in ra để sàng lọc một loạt thông tin. Tôi muốn chỉ có thể nhìn thấy các dòng sau khi tìm thấy một mẫu.

Tôi tưởng tượng việc sử dụng một giải pháp để trông giống như

echoer | solution_command <pattern>

Lý tưởng nhất patternlà một biểu thức chính quy, nhưng chuỗi giá trị cứng sẽ đủ cho tôi.


Vậy mẫu có thể nhiều chuỗi?
Inian

Một quả địa cầu? Bạn có nghĩa là một biểu thức thường xuyên? Globs chỉ có ý nghĩa cho việc mở rộng tên tập tin.
terdon

@Inian Tôi không chắc là tôi hiểu câu hỏi. Bạn có nghĩa là hỏi nếu tôi muốn điều này làm việc với sự bất đồng?
dùng23146

Câu trả lời:


21

AWK có thể làm điều này với các phạm vi mẫu, cho phép sử dụng bất kỳ biểu thức chính quy nào:

echoer | awk '/pattern/,0'

sẽ in echoerđầu ra bắt đầu bằng khớp dòng đầu tiên pattern.

AWK dựa trên mô hình và thường được sử dụng với một mô hình nếu mô hình này phù hợp, thực hiện kiểu tiếp cận này. Mô hình này có thể là một loạt các mô hình, được định nghĩa là mô hình khi mô hình này khớp, bắt đầu thực hiện điều này, cho đến khi mô hình khác này khớp với mô hình; điều này được chỉ định bằng cách viết hai mẫu được phân tách bằng dấu phẩy, như trên. Các mẫu có thể khớp với văn bản, như trong /pattern/, trong đó dòng hiện tại được kiểm tra so với mẫu, được hiểu là biểu thức chính quy; chúng cũng có thể là biểu thức tổng quát, được đánh giá cho mỗi dòng và được coi là khớp nếu kết quả của chúng khác không hoặc không trống.

Trong AWK, hành động mặc định là in dòng hiện tại.

Đặt tất cả những thứ này lại với nhau, awk '/pattern/,0'tìm kiếm các dòng khớp patternvà khi tìm thấy một dòng, áp dụng hành động mặc định cho tất cả các dòng cho đến khi 0điều kiện khớp (không khác không). awk '/pattern/,""'cũng sẽ làm việc

Các nhãn hiệu gawk đi vào chi tiết nhiều hơn nữa.


3
Tôi đã không nhận thức được ngữ nghĩa phạm vi với số 0 là kết thúc của phạm vi. Cảm ơn!
Kusalananda

@StephenKitt Điều này thật tuyệt! Nếu tôi muốn in cho đến khi nó khớp 0thì sao? Nó sẽ là /pattern/,/0/gì? Câu trả lời sẽ trông như thế nào khi viết rõ ràng hành động mặc định?
dùng23146

@ user23146 có, /pattern/,/0/sẽ in cho đến khi tìm thấy một dòng (bản ghi) có chứa 0 0. Viết đoạn trích trong câu trả lời bằng một hành động rõ ràng đưa ra /pattern/,0 { print $0 }, hoặc tương đương /pattern/,0 { print }.
Stephen Kitt

7

sedTương đương bắt buộc của một @ StephenKitt awk:

sed '/pattern/,$!d'

patternđược hiểu là Biểu thức chính quy cơ bản như trong grep(trái ngược với Biểu thức chính quy mở rộng trong awk/ egrep/ grep -E). Một số sedtriển khai có tùy chọn -E(BSD, ast, GNU / busybox gần đây, POSIX sớm) hoặc -r(GNU, ssed, busybox, một số BSD gần đây) để biến nó thành Biểu thức chính quy mở rộng thay thế và một số có -P(ast) hoặc -R(ssed) để thực hiện một biểu thức chính quy như perl.

Với perl:

perl -ne 'print if /pattern/ .. undef'

4

với GNU và * BSD grep:

grep -A1000000000 pattern file

Trừ khi tệp của bạn có nhiều hơn 1M dòng, đó là nó.


0

Nếu bạn đang sử dụng một máy nhắn tin như lessđể xem đầu ra từ lệnh

less +pattern

0

awk đối với các dòng sau (nhưng không bao gồm) mẫu đầu tiên khớp

Nếu dòng chứa mẫu kích hoạt tương đương với "CẮT TẠI ĐÂY", bạn có thể bỏ qua nó từ đầu ra được in:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Mỗi dòng đầu vào chạy qua hai thành phần trong mã awk. Thành phần đầu tiên là flag, awk diễn giải là "in dòng nếu biến flaglà khác không". Vì các biến awk là 0 theo mặc định, điều này ban đầu sẽ không in bất cứ thứ gì.

Thành phần thứ hai /pattern/ { flag=1 }, đặt cờ thành 1 ngay khi phát hiện mẫu và cờ giữ giá trị đó cho phần còn lại của hoạt động.

Vào thời điểm mẫu được phát hiện lần đầu tiên, cơ hội in dòng đầu vào đó đã trôi qua. Bất kỳ dòng tiếp theo (bao gồm các dòng bổ sung có chứa mẫu) sẽ in.


0

Bash

Một chút lộn xộn, nhưng nó hoạt động.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Phiên bản này dựa vào cat, nhưng nó dễ hiểu hơn.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.