it-swarm-vi.com

Thuyết phục grep để xuất tất cả các dòng, không chỉ những dòng có khớp

Nói rằng tôi có tập tin sau:

$ cat test

test line 1
test line 2
line without the search Word
another line without it
test line 3 with two test words
test line 4

Theo mặc định, grep trả về mỗi dòng có chứa cụm từ tìm kiếm:

$ grep test test

test line 1
test line 2
test line 3 with two test words
test line 4

Vượt qua --color tham số tới grep sẽ làm cho nó làm nổi bật phần của dòng khớp với biểu thức tìm kiếm, nhưng nó vẫn chỉ trả về các dòng có chứa biểu thức. Có cách nào để có được grep để xuất mọi dòng trong tệp nguồn, nhưng làm nổi bật các kết quả khớp không?

Bản hack khủng khiếp hiện tại của tôi để thực hiện điều này (ít nhất là trên các tệp không có hơn 10000 dòng liên tiếp không có kết quả trùng khớp) là:

$ grep -B 9999 -A 9999 test test

Screenshot of the two commands

Nếu grep không thể thực hiện được điều này, có công cụ dòng lệnh nào khác có chức năng tương tự không? Tôi đã đấu tranh với ack , nhưng dường như nó cũng không có tùy chọn nào cho nó.

127
Michael Mrozek
grep --color -E "test|$" yourfile

Những gì chúng tôi đang làm ở đây là khớp với $ mẫu và mẫu thử, rõ ràng là $ không có gì để đánh bóng nên chỉ có mẫu thử có màu. Các -E chỉ bật kết hợp regex mở rộng.

Bạn có thể tạo một hàm từ nó dễ dàng như thế này:

highlight () { grep --color -E "$1|$" "${@:1}" ; }
194
jacksonh
ack --passthru --color string file

đối với Ubuntu và Debian, hãy sử dụng ack-grep thay vì ack

ack-grep --passthru --color string file

Một cách khác để làm điều này đúng cách có thể di chuyển với grep (bên cạnh việc sử dụng hai biểu thức chính với xen kẽ như trong câu trả lời được chấp nhận) là thông qua mẫu null (và chuỗi null tương ứng).
[.__.] Nó sẽ hoạt động tốt như nhau với cả -E-F chuyển từ, theo tiêu chuẩn :

-E
    Match using extended regular expressions. 
    [...] A null ERE shall match every line.

-F
    Match using fixed strings.
    [...] A null string shall match every line.

Vì vậy, nó chỉ đơn giản là vấn đề chạy

grep -E -e '' -e 'pattern' infile

và tương ứng

grep -F -e '' -e 'string' infile
13
don_crissti

Tôi có chức năng sau đây mà tôi sử dụng cho những thứ đó:

highlight () {
    Perl -pe "s/$1/\e[1;31;43m$&\e[0m/g"
}

Bên trong nó trông có vẻ xấu xí, nó đẹp và dễ sử dụng, như vậy:

cat some_file.txt | highlight some_Word

hoặc, cho một ví dụ thực tế hơn một chút:

tail -f console.log | highlight ERROR

Bạn có thể thay đổi màu sắc thành bất cứ thứ gì bạn thích (có thể khó với grep - tôi không chắc chắn) bằng cách thay đổi 13143 (sau \e[) đến các giá trị khác nhau. để sử dụng là tất cả hơn địa điểm , nhưng đây là phần giới thiệu nhanh: 1 in đậm văn bản, 31 làm cho nó màu đỏ và 43 cho một nền màu vàng. 32 hoặc là 33 sẽ có màu khác nhau và 44 hoặc là 45 sẽ là nền tảng khác nhau: bạn có được ý tưởng. Bạn thậm chí có thể làm cho nó nhấp nháy (với một 5) nếu bạn rất nghiêng.

Điều này không sử dụng bất kỳ mô-đun Perl đặc biệt nào và Perl là gần như có mặt ở khắp mọi nơi, vì vậy tôi sẽ mong đợi nó hoạt động ở mọi nơi. Giải pháp grep rất thông minh, nhưng công tắc --color trên grep không có sẵn ở mọi nơi. Chẳng hạn, tôi vừa thử giải pháp này trên hộp Solaris đang chạy bash và một ksh khác đang chạy và máy Mac OS X cục bộ của tôi chạy zsh. Tất cả đều hoạt động tốt. Solaris nghẹn ngào khi grep --color giải pháp, tuy nhiên.

Ngoài ra, ack rất tuyệt và tôi giới thiệu nó cho bất kỳ ai chưa phát hiện ra nó, nhưng tôi đã gặp một số vấn đề khi cài đặt nó trên một vài trong số nhiều máy chủ mà tôi làm việc. (Tôi quên tại sao: Tôi nghĩ liên quan đến các mô-đun Perl mà nó yêu cầu.)

Vì tôi không nghĩ rằng tôi đã từng làm việc trên hộp Unix mà không đã cài đặt Perl (ngoại trừ các hệ thống kiểu nhúng, bộ định tuyến Linksys, v.v.) Tôi muốn nói rằng đây là một giải pháp có thể sử dụng phổ biến.

11
iconoclast

Thay vì sử dụng Grep, bạn có thể sử dụng Ít hơn:

less file

Tìm kiếm như thế này: /pattern Enter

Điều này sẽ:

  1. cuộn đến dòng khớp đầu tiên
  2. đầu ra mỗi dòng bắt đầu từ đó
  3. làm nổi bật tất cả các trận đấu

Để cuộn đến dòng phù hợp tiếp theo: n

Để cuộn đến dòng khớp trước đó: N

Để chuyển đổi tô sáng: Esc u

Ngoài ra, bạn có thể thay đổi tô sáng mà nếu bạn thích.

3
Steven Penny

Bạn co thể thử:

Perl -MTERM::ANSIColor -nle '/pattern/ ? print colored($_, 'color') : print' test

Tuy nhiên, không dễ mang theo, và ngay cả khi Perl được cài đặt, bạn có thể cần phải tải xuống một mô-đun khác. Ngoài ra, nó sẽ tô màu toàn bộ dòng, không chỉ Word tìm kiếm.

2
gvkv

Không có câu trả lời nào được đưa ra cho đến nay không cung cấp giải pháp xách tay .

Đây là một chiếc di động1 Hàm Shell I đã được đăng trong câu hỏi đóng dưới dạng trùng lặp không yêu cầu các công cụ không chuẩn hoặc tiện ích mở rộng không chuẩn được cung cấp với Perl, ack, ggrep, gsed, bash và những lượt thích nhưng chỉ cần Shell POSIX và các tiện ích bắt buộc POSIX sedprintf:

grepc()
{
  pattern=$1
  shift
  esc=$(printf "\033")
  sed 's"'"$pattern"'"'$esc'[32m&'$esc'[0m"g' "[email protected]"
}

Bạn có thể sử dụng nó theo cách đó:

grepc string_to_search [file ...]

Màu sắc nổi bật có thể được điều chỉnh bằng cách sử dụng một trong các mã này trong đối số lệnh sed (32m có màu xanh lá cây ở đây):

30m black
31m red
33m yellow
34m blue
35m Magenta
36m cyan
37m white
7m reverse video

1 Miễn là thiết bị đầu cuối của bạn hỗ trợ các chuỗi thoát màu ANSI.

2
jlliagre

ripgrep

Sử dụng ripgrep với --passthru tham số:

rg --passthru pattern file.txt

Đó là một trong công cụ grepping nhanh nhất , vì nó được xây dựng trên đỉnh công cụ regex của Rust sử dụng automata hữu hạn, SIMD và tối ưu hóa theo nghĩa đen tích cực để giúp tìm kiếm rất nhanh.

--passthru - In cả hai dòng khớp và không khớp.

Một cách khác để đạt được hiệu ứng tương tự là sửa đổi mẫu của bạn để khớp với chuỗi trống. Ví dụ: nếu bạn đang tìm kiếm bằng cách sử dụng rg foo sau đó sử dụng rg "^|foo" thay vào đó sẽ phát ra mọi dòng trong mỗi tệp được tìm kiếm, nhưng chỉ các lần xuất hiện của foo sẽ được tô sáng. Cờ này cho phép hành vi tương tự mà không cần phải sửa đổi mẫu.

2
kenorb

Có một cách dễ dàng hơn nhiều để làm điều này cho GNU grep nhưng tôi không nghĩ rằng nó có thể mang theo được (tức là, BSD grep):

Trong một đường ống:

cat <file> | grep --color=always -z <query>

Trên một tập tin:

grep --color=always -z <query> <file>

Tín dụng đi đến câu trả lời của Cyrus tại đây .

1
Erik Nomitch

Phiên bản sed, hoạt động trên cả bashash.

#highlight
hsed(){
    local pattern="$1"
    shift
    local r=`echo -e '\e'[31m`
    local c=`echo -e '\e'[0m`
    sed "s:${pattern//:/\:}:$r\0$c:g" "[email protected]"
}
0
yurenchen

OP đã yêu cầu grep, và đó là những gì I RECOMMEND; nhưng sau khi cố gắng hết sức để giải quyết vấn đề với sed, đối với bản ghi, đây là một giải pháp đơn giản với nó:

sed $'s/main/\E[31m&\E[0m/g' testt.c

hoặc là

cat testt.c | sed $'s/main/\E[31m&\E[0m/g'

Sẽ Sơn main màu đỏ.

  • \E[31m: chuỗi bắt đầu màu đỏ
  • \E[0m: đánh dấu màu đã hoàn thành
  • &: mẫu phù hợp
  • /g: tất cả các từ trong một dòng, không chỉ đầu tiên
  • $'string' là chuỗi bash với các ký tự thoát được giải thích

Về grep, nó cũng hoạt động bằng cách sử dụng ^ (bắt đầu dòng) thay vì $ (kết thúc dòng). Thí dụ:

egrep "^|main" testt.c

Và chỉ để hiển thị bí danh điên rồ này TÔI KHÔNG GIỚI THIỆ, bạn thậm chí có thể để các trích dẫn mở:

alias h='egrep -e"^|'
h main" testt.c
cat testt.c | h main"

tất cả công việc! :) Đừng lo lắng nếu bạn quên đóng trích dẫn, bash sẽ nhớ bạn với "ký tự dòng tiếp tục".

0
Dr Beco