Với GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Giải trình:
-o
=> Chỉ in những gì bạn khớp
-P
=> Sử dụng biểu thức chính quy theo kiểu Perl
- Regex cho biết khớp 0 với các
$N
ký tự theo foo
sau là 0 đến các $N
ký tự.
Nếu bạn không có GNU grep
:
find . -type f -exec \
perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
Giải trình:
Vì chúng tôi không còn có thể dựa vào grep
GNU grep
, chúng tôi sử dụng find
để tìm kiếm các tệp đệ quy ( -r
hành động của GNU grep
). Đối với mỗi tệp được tìm thấy, chúng tôi thực thi đoạn mã Perl.
Công tắc Perl:
-n
Đọc từng dòng tệp
-l
Xóa dòng mới ở cuối mỗi dòng và đặt lại khi in
-e
Xử lý chuỗi sau đây dưới dạng mã
Đoạn mã Perl đang làm về cơ bản giống như grep
. Nó bắt đầu bằng cách đặt một biến $N
cho số lượng ký tự ngữ cảnh bạn muốn. Điều BEGIN{}
này có nghĩa là điều này chỉ được thực hiện một lần khi bắt đầu thực hiện không phải một lần cho mỗi dòng trong mỗi tệp.
Câu lệnh được thực thi cho mỗi dòng là in dòng nếu thay thế regex hoạt động.
Các regex:
- Khớp bất kỳ thứ cũ nào một cách lười biếng 1 ở đầu dòng (
^.*?
) theo sau .{0,$N}
như trong grep
trường hợp, tiếp foo
theo là một thứ khác .{0,$N}
và cuối cùng khớp với bất kỳ thứ cũ nào một cách lười biếng cho đến cuối dòng ( .*?$
).
- Chúng tôi thay thế bằng
$ARGV:$1
. $ARGV
là một biến số ma thuật chứa tên của tệp hiện tại đang được đọc. $1
là những gì parens phù hợp: bối cảnh trong trường hợp này.
- Các trận đấu lười biếng ở hai đầu được yêu cầu vì một trận đấu tham lam sẽ ăn tất cả các nhân vật trước
foo
mà không khớp (vì .{0,$N}
được phép khớp 0 lần).
1 Nghĩa là, không nên khớp bất cứ thứ gì trừ khi điều này sẽ khiến trận đấu tổng thể thất bại. Trong ngắn hạn, phù hợp với càng ít nhân vật càng tốt.