Cách cắt ngắn các dòng kết hợp dài được trả về bởi grep hoặc ack


89

Tôi muốn chạy ack hoặc grep trên các tệp HTML thường có các dòng rất dài. Tôi không muốn nhìn thấy những hàng dài rất dài lặp đi lặp lại. Nhưng tôi chỉ muốn xem phần đó của một dòng dài bao quanh một chuỗi khớp với biểu thức chính quy. Làm cách nào để tôi có được điều này bằng cách sử dụng bất kỳ sự kết hợp nào của các công cụ Unix?


1
Là gì ack? Nó có phải là một lệnh bạn sử dụng khi bạn không thích một cái gì đó? Một cái gì đó như thế ack file_with_long_lines | grep patternnào? :-)
Alok Singhal

6
@Alok ack(được gọi là ack-greptrên Debian) đang grepsử dụng steroid. Nó cũng có --thpppttùy chọn (không đùa). betterthangrep.com
ZoogieZork

Cảm ơn. Tôi đã học được vài điều hôm nay.
Alok Singhal

1
Trong khi --thpppttính năng có phần gây tranh cãi, những lợi thế quan trọng dường như là bạn có thể sử dụng Perl regexes trực tiếp, không phải một số điên [[:space:]]và các nhân vật thích {, [vv thay đổi nghĩa với -e-Echuyển mạch trong một cách mà không thể nhớ.
Evgeni Sergeev

Câu trả lời:


99

Bạn có thể sử dụng tùy chọn grep -o, có thể kết hợp với việc thay đổi mẫu của bạn thành ".{0,10}<original pattern>.{0,10}"để xem một số ngữ cảnh xung quanh nó:

       -o, - chỉ phù hợp
              Chỉ hiển thị một phần của đường khớp phù hợp với PATTERN.

..hoặc -c:

       -c, --count
              Ức chế sản lượng bình thường; thay vào đó in một số dòng phù hợp
              cho mỗi tệp đầu vào. Với tùy chọn -v, --invert-match (xem
              dưới đây), đếm các dòng không khớp.

44
ví dụ: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud

14
bạn nên thay đổi câu trả lời thành tùy chọn add -E như được hiển thị bởi @Renaud (tùy chọn mẫu mở rộng), hoặc mẫu được đề xuất để mở rộng ngữ cảnh sẽ không hoạt động.
kriss

Có thể không cần thiết nhưng đây là một ví dụ: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt bản inqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera

Điều này hoạt động tốt; nhưng nhược điểm đáng chú ý là khi sử dụng, ví dụ, oE ".{0,20}mysearchstring.{0,20}"bạn mất điểm đánh dấu của chuỗi "gốc" bên trong so với ngữ cảnh, bởi vì toàn bộ điều trở thành mẫu tìm kiếm. Rất thích tìm cách giữ một số ngữ cảnh không được đánh dấu xung quanh kết quả tìm kiếm, để quét trực quan và giải thích kết quả dễ dàng hơn nhiều.
Aaron Wallentine

1
Ồ, đây là giải pháp cho vấn đề nổi bật do sử dụng cách -oE ".{0,x}foo.{0,x}"tiếp cận ( xsố ký tự của ngữ cảnh là ở đâu) - append `| grep foo `đến cuối. Hoạt động cho cả giải pháp ack hoặc grep. Các giải pháp khác cũng có ở đây: unix.stackexchange.com/questions/163726/…
Aaron Wallentine

44

Kết quả của bạn thông qua cut. Tôi cũng đang xem xét thêm một --cutcông tắc để bạn có thể nói --cut=80và chỉ nhận được 80 cột.


8
Điều gì sẽ xảy ra nếu phần phù hợp không có trong 80 ký tự đầu tiên?
Ether

3
FWIW Tôi nối | cut=c1-120với grep, làm việc cho tôi (mặc dù không biết làm thế nào để cắt văn bản xung quanh phù hợp)
Jake Rayson

26
| cut=c1-120không hiệu quả với tôi, tôi cần phải làm| cut -c1-120
Ken Cochrane

1
Tôi nghĩ @edib là chính xác trong cú pháp | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS

1
@AndyLester: Còn một --no-wraptùy chọn sử dụng $COLUMNSthì sao?
naught101

25

Bạn có thể sử dụng ít hơn làm máy nhắn tin cho ack và cắt các dòng dài: ack --pager="less -S" Thao tác này giữ lại dòng dài nhưng để nó trên một dòng thay vì gói. Để xem nhiều dòng hơn, hãy cuộn sang trái / phải ít hơn bằng các phím mũi tên.

Tôi có thiết lập bí danh sau cho ack để thực hiện việc này:

alias ick='ack -i --pager="less -R -S"' 

2
Xin lưu ý rằng bạn có thể đặt --pagerlệnh đó trong tệp ~ / .ackrc của mình, nếu bạn luôn muốn sử dụng nó.
Andy Lester

Điều này có vẻ như là giải pháp tốt nhất cho đến nay cho vấn đề mà tôi rất khó chịu này. Tôi ước tôi biết cách sử dụng ack.
Brian Peterson

@BrianPeterson ackkhá giống grep, chỉ đơn giản hơn trong những trường hợp phổ biến nhất
Aaron Wallentine

8
cut -c 1-100

nhận các ký tự từ 1 đến 100.


2

Lấy từ: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

Cách tiếp cận ".{0,10}<original pattern>.{0,10}"được đề xuất là hoàn toàn tốt, ngoại trừ việc màu highlight thường bị rối. Tôi đã tạo một tập lệnh có đầu ra tương tự nhưng màu sắc cũng được giữ nguyên:

#!/bin/bash

# Usage:
#   grepl PATTERN [FILE]

# how many characters around the searching keyword should be shown?
context_length=10

# What is the length of the control character for the color before and after the
# matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))

grep -E --color=always "$1" $2 |
grep --color=none -oE \
    ".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"

Giả sử tập lệnh được lưu dưới dạng grepl, sau đó grepl pattern file_with_long_linessẽ hiển thị các dòng phù hợp nhưng chỉ với 10 ký tự xung quanh chuỗi phù hợp.


Hoạt động, nhưng đầu ra rác theo sau cho tôi, như thế này: ^ [[? 62; 9; c. Tôi chưa thử gỡ lỗi vì câu trả lời của @Jonah Braun làm tôi hài lòng.
sondra.kinsey

1

Đây là những gì tôi làm:

function grep () {
  tput rmam;
  command grep "$@";
  tput smam;
}

Trong .bash_profile của tôi, tôi ghi đè grep để nó tự động chạy tput rmamtrước và tput smamsau, điều này đã vô hiệu hóa gói và sau đó bật lại nó.


Đó là một sự thay thế tuyệt vời - ngoại trừ nếu trận đấu thực sự sau đó không xuất hiện trên màn hình ...
Xerus

1

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

Trong trường hợp bất thường mà bạn không thể sử dụng -E, bạn có thể sử dụng:

grep -oe ".\{0,10\}error.\{0,10\}" mylogfile.txt

0

Tôi đặt những điều sau vào .bashrc:

grepl() {
    $(which grep) --color=always $@ | less -RS
}

Sau đó, bạn có thể sử dụng grepltrên dòng lệnh với bất kỳ đối số nào có sẵn grep. Sử dụng các phím mũi tên để xem phần đuôi của các dòng dài hơn. Sử dụng qđể bỏ thuốc lá.

Giải trình:

  • grepl() {: Xác định một chức năng mới sẽ có sẵn trong mọi bảng điều khiển bash (mới).
  • $(which grep): Nhận đường dẫn đầy đủ của grep. (Ubuntu định nghĩa một bí danh greptương đương với grep --color=auto. Chúng tôi không muốn bí danh đó mà là bí danh gốc grep.)
  • --color=always: Tô màu đầu ra. ( --color=autotừ bí danh sẽ không hoạt động vì grepphát hiện ra rằng đầu ra được đưa vào một đường ống và khi đó sẽ không tô màu.)
  • $@: Đặt tất cả các đối số được cung cấp cho greplhàm ở đây.
  • less: Hiển thị các dòng sử dụng less
  • -R: Hiển thị màu sắc
  • S: Đừng ngắt dòng dài
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.