Nhân vật Grep trước và sau trận đấu?


144

Sử dụng cái này:

grep -A1 -B1 "test_pattern" file

sẽ tạo một dòng trước và sau mẫu phù hợp trong tệp. Có cách nào để hiển thị không phải dòng mà là một số ký tự được chỉ định không?

Các dòng trong tệp của tôi khá lớn nên tôi không quan tâm đến việc in toàn bộ dòng mà chỉ quan sát trận đấu trong ngữ cảnh. Có bất cứ đề nghị nào cho việc làm như thế này hả?


Câu trả lời:


183

3 ký tự trước và 4 ký tự sau

$> echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}'
23_string_and

5
Một câu trả lời tốt cho một lượng nhỏ dữ liệu, nhưng nó bắt đầu chậm khi bạn khớp> 100 ký tự - ví dụ: trong tệp xml khổng lồ của tôi, tôi muốn {1.200} trước và sau và quá chậm để sử dụng.
Benubird

3
Phiên bản awk của @amit_g nhanh hơn nhiều.
ssobczak

6
Không có sẵn trên Mac OSX, vì vậy đây thực sự không phải là một giải pháp có sẵn rộng rãi. Phiên bản -E (được liệt kê dưới đây) là một giải pháp tốt hơn. -P là gì? Đọc trên ... -P, --perl-regrec Phiên dịch MẪU như một biểu thức chính quy Perl (PCRE, xem bên dưới). Điều này mang tính thử nghiệm cao và grep -P có thể cảnh báo các tính năng chưa được thực hiện.
Xofo

2
Trên OSX cài đặt qua: brew install homebrew/dupes/grepvà chạy nó dưới dạng ggrep.
kenorb

1
Theo ngụ ý của @Benubird, điều này sẽ không thể sử dụng cho các tệp lớn với môi trường rộng vừa phải mong muốn cho mục tiêu khớp.
matanster

113
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

Điều này sẽ phù hợp với tối đa 5 ký tự trước và sau mẫu của bạn. Công tắc -o báo cho grep chỉ hiển thị kết quả khớp và -E để sử dụng biểu thức chính quy mở rộng. Hãy chắc chắn để đặt các trích dẫn xung quanh biểu thức của bạn, nếu không nó có thể được giải thích bởi shell.


1
Câu trả lời hay, thú vị là nó được giới hạn ở mức 2 ^ 8-1 cho độ dài trong {} vì vậy {0,255}các tác phẩm {0,256}mang lạigrep: invalid repetition count(s)
CodeMonkey

Điều này dường như nhận được ít hiệu suất hơn đáng kể khi tôi tăng số lượng ký tự phù hợp (5 -> 25 -> 50), có ý tưởng nào tại sao không?
Adam Hughes

37

Bạn đã có thể sử dụng

awk '/test_pattern/ {
    match($0, /test_pattern/); print substr($0, RSTART - 10, RLENGTH + 20);
}' file

2
Hoạt động độc đáo ngay cả với các tệp lớn hơn một chút
Touko

4
Làm thế nào bạn có thể sử dụng điều này để tìm nhiều trận đấu trên mỗi dòng?
koox00

1
Tầm quan trọng của số đầu tiên trong các cặp ngoặc nhọn là gì? Giống như số 0 trong "grep -E -o". {0,5} test_potype. {0,5} "test.txt"?
Fan hâm mộ của Lew Rockwell

Nó thực sự nhanh hơn nhưng không chính xác như câu trả lời của @ ekse.
Abdollah

24

Ý bạn là, như thế này:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

?

Điều đó sẽ in tối đa hai mươi ký tự ở hai bên test_pattern. Các \{0,20\}ký hiệu giống như *, nhưng quy định cụ thể số không đến hai mươi lần lặp lại thay vì bằng không hoặc PIM -onói để chỉ hiển thị các trận đấu chính nó, chứ không phải là toàn bộ dòng.


Lệnh này không hiệu quả với tôi:grep: Invalid content of \{\}
Alexander Pravdin

0

Với gawk, bạn có thể sử dụng chức năng khớp:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

Nếu bạn ổn với perlgiải pháp linh hoạt hơn: Sau đây sẽ in ba ký tự trước mẫu tiếp theo mẫu thực tế và sau đó là 5 ký tự sau mẫu.

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

Điều này cũng có thể được áp dụng cho các từ thay vì chỉ các ký tự. Theo dõi sẽ in một từ trước chuỗi kết hợp thực tế.

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

Sau đây sẽ in một từ sau mẫu:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

Sau đây sẽ in một từ trước mẫu, sau đó là từ thực tế và sau đó một từ sau mẫu:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

0

Bạn có thể sử dụng grep regrec để tìm + grep thứ hai để làm nổi bật

echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}' | grep string

23_ chuỗi_and

nhập mô tả hình ảnh ở đây


0

Tôi sẽ không bao giờ dễ dàng nhớ những công cụ sửa đổi lệnh khó hiểu này vì vậy tôi đã trả lời trên cùng và biến nó thành một hàm trong ~/.bashrctệp của mình :


cgrep() {
    # For files that are arrays 10's of thousands of characters print.
    # Use cpgrep to print 30 characters before and after search patttern.
    if [ $# -eq 2 ] ; then
        # Format was 'cgrep "search string" /path/to/filename'
        grep -o -P ".{0,30}$1.{0,30}" "$2"
    else
        # Format was 'cat /path/to/filename | cgrep "search string"
        grep -o -P ".{0,30}$1.{0,30}"
    fi
} # cgrep()

Đây là những gì nó trông giống như trong hành động:

$ ll /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

-rw-r--r-- 1 rick rick 25780 Jul  3 19:05 /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

$ cat /tmp/rick/scp.Mf7UdS/Mf7UdS.Source | cgrep "Link to iconic"

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

$ cgrep "Link to iconic" /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

Các tập tin trong câu hỏi là một dòng 25K liên tục và vô vọng để tìm thấy những gì bạn đang tìm kiếm sử dụng thường xuyên grep.

Lưu ý hai cách khác nhau mà bạn có thể gọi phương thức cgrepsong song đó grep.

Có một cách "nhanh hơn" để tạo hàm trong đó "$ 2" chỉ được thông qua khi được đặt sẽ lưu 4 dòng mã. Tôi không có nó mặc dù. Một cái gì đó như ${parm2} $parm2. Nếu tôi tìm thấy nó, tôi sẽ sửa lại chức năng và câu trả lời này.

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.