วิธีตัดทอนบรรทัดการจับคู่แบบยาวที่ส่งคืนโดย grep หรือ ack


91

ฉันต้องการเรียกใช้ ack หรือ grep บนไฟล์ HTML ที่มักมีบรรทัดยาวมาก ฉันไม่อยากเห็นเส้นยาว ๆ ที่พันซ้ำ ๆ แต่ฉันอยากเห็นแค่ส่วนนั้นของเส้นยาวที่ล้อมรอบสตริงที่ตรงกับนิพจน์ทั่วไป ฉันจะได้รับสิ่งนี้โดยใช้เครื่องมือ Unix ร่วมกันได้อย่างไร


1
คืออะไรack? เป็นคำสั่งที่คุณใช้เมื่อคุณไม่ชอบอะไรหรือเปล่า? บางอย่างเช่นack file_with_long_lines | grep pattern? :-)
Alok Singhal

6
@Alok ack(รู้จักกันในชื่อack-grepDebian) อยู่grepบนเตียรอยด์ นอกจากนี้ยังมี--thppptตัวเลือก (ไม่ได้ล้อเล่น) betterthangrep.com
ZoogieZork

ขอบคุณ. ฉันได้เรียนรู้บางสิ่งในวันนี้
Alok Singhal

1
ในขณะที่--thppptคุณสมบัติค่อนข้างขัดแย้งได้เปรียบที่ปรากฏกุญแจสำคัญที่จะเป็นไปได้ว่าคุณสามารถใช้ Perl regexes โดยตรงไม่บางบ้า[[:space:]]และตัวอักษรที่ชอบ{, [ฯลฯ การเปลี่ยนความหมายกับ-eและ-Eสวิทช์ในทางที่เป็นไปไม่ได้ที่จะจำ
Evgeni Sergeev

คำตอบ:


101

คุณสามารถใช้ตัวเลือก grep -oซึ่งอาจใช้ร่วมกับการเปลี่ยนรูปแบบของคุณเป็น".{0,10}<original pattern>.{0,10}"เพื่อดูบริบทรอบ ๆ :

       -o, - จับคู่เท่านั้น
              แสดงเฉพาะส่วนของบรรทัดที่ตรงกันที่ตรงกับ PATTERN

.. หรือ-c:

       -c, - นับ
              ปราบปรามเอาต์พุตปกติ พิมพ์จำนวนบรรทัดที่ตรงกันแทน
              สำหรับไฟล์อินพุตแต่ละไฟล์ ด้วยตัวเลือก -v, --invert-match (ดู
              ด้านล่าง) นับบรรทัดที่ไม่ตรงกัน

44
ตัวอย่าง: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud

14
คุณควรเปลี่ยนคำตอบเป็นตัวเลือกเพิ่ม -E ตามที่แสดงโดย @Renaud (ตัวเลือกรูปแบบขยาย) หรือรูปแบบที่เสนอสำหรับการขยายบริบทจะไม่ทำงาน
kriss

อาจจะไม่จำเป็น แต่นี่เป็นตัวอย่าง: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt ภาพพิมพ์qqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera

1
ทำงานได้ดี แต่ข้อเสียที่น่าสังเกตคือเมื่อใช้เช่นoE ".{0,20}mysearchstring.{0,20}"คุณสูญเสียการไฮไลต์ของสตริง "ต้นฉบับ" ภายในเทียบกับบริบทเนื่องจากสิ่งทั้งหมดกลายเป็นรูปแบบการค้นหา ชอบที่จะหาวิธีที่จะรักษาบริบทที่ไม่ได้เน้นไว้รอบ ๆ ผลการค้นหาเพื่อการสแกนและการตีความผลลัพธ์ด้วยภาพที่ง่ายขึ้นมาก
Aaron Wallentine

1
โอ้นี่คือวิธีแก้ปัญหาการไฮไลต์ที่เกิดจากการใช้-oE ".{0,x}foo.{0,x}"วิธีการ ( xจำนวนอักขระของบริบทอยู่ที่ไหน) - ต่อท้าย `| grep foo 'จนจบ ใช้ได้กับโซลูชัน ack หรือ grep วิธีแก้ไขเพิ่มเติมที่นี่: unix.stackexchange.com/questions/163726/…
Aaron Wallentine

45

cutท่อผลลัพธ์ของคุณผ่าน ฉันกำลังพิจารณาเพิ่ม--cutสวิตช์เพื่อให้คุณสามารถพูดได้--cut=80และรับเพียง 80 คอลัมน์


8
จะเกิดอะไรขึ้นถ้าส่วนที่ตรงกันไม่อยู่ใน 80 อักขระแรก?
Ether

3
FWIW ฉันต่อท้าย| cut=c1-120grep ทำงานให้ฉัน (แม้ว่าไม่รู้ว่าจะตัดข้อความที่ตรงกันอย่างไร)
Jake Rayson

26
| cut=c1-120ไม่ได้ผลสำหรับฉันฉันต้องทำ| cut -c1-120
Ken Cochrane

1
ฉันคิดว่า @edib ถูกต้องในไวยากรณ์| cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS

1
@AndyLester: แล้ว--no-wrapตัวเลือกที่ใช้$COLUMNSล่ะ?
naught101

25

คุณสามารถใช้น้อยลงเป็นเพจเจอร์สำหรับ ack และสับเส้นยาว: ack --pager="less -S" สิ่งนี้จะคงไว้ซึ่งเส้นยาว แต่ทิ้งไว้ในบรรทัดเดียวแทนที่จะห่อ หากต้องการดูเส้นเพิ่มเติมให้เลื่อนไปทางซ้าย / ขวาโดยใช้ปุ่มลูกศรน้อยลง

ฉันมีการตั้งค่านามแฝงต่อไปนี้เพื่อให้ ack ทำสิ่งนี้:

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

2
โปรดทราบว่าคุณสามารถใส่--pagerคำสั่งนั้นในไฟล์ ~ / .ackrc ของคุณได้หากคุณต้องการใช้เสมอ
Andy Lester

นี่ดูเหมือนเป็นทางออกที่ดีที่สุดสำหรับปัญหานี้ที่ทำให้ฉันมีปัญหามาก ackฉันหวังว่าฉันรู้วิธีการใช้งาน
Brian Peterson

@BrianPeterson ackค่อนข้างเหมือนgrepกันง่ายกว่าในกรณีที่พบบ่อยที่สุดเท่านั้น
Aaron Wallentine


2

นำมาจาก: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

แนวทางที่แนะนำ".{0,10}<original pattern>.{0,10}"นั้นดีอย่างสมบูรณ์ยกเว้นว่าสีไฮไลต์มักจะเลอะ ฉันได้สร้างสคริปต์ที่มีผลลัพธ์ที่คล้ายกัน แต่ยังคงรักษาสีไว้:

#!/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))}"

สมมติว่าสคริปต์ถูกบันทึกเป็นgreplแล้วgrepl pattern file_with_long_linesควรแสดงบรรทัดที่ตรงกัน แต่มีอักขระเพียง 10 ตัวรอบสตริงที่ตรงกัน


ใช้งานได้ แต่ส่งออกขยะต่อท้ายสำหรับฉันดังนี้: ^ [[? 62; 9; c. ฉันยังไม่ได้ลองดีบักเพราะคำตอบของ @Jonah Braunทำให้ฉันพอใจ
sondra.kinsey

2

ป้อนคำอธิบายภาพที่นี่

ในสถานการณ์ที่ไม่ปกติซึ่งคุณไม่-Eสามารถใช้ได้คุณสามารถใช้:

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

1

นี่คือสิ่งที่ฉันทำ:

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

ใน. bash_profile ของฉันฉันจะแทนที่ grep เพื่อให้มันทำงานtput rmamก่อนและtput smamหลังโดยอัตโนมัติซึ่งปิดใช้งานการตัดแล้วเปิดใช้งานใหม่


นั่นเป็นทางเลือกที่ดียกเว้นว่าการแข่งขันจริงจะอยู่นอกหน้าจอ ...
Xerus

0

ฉันใส่สิ่งต่อไปนี้ลงใน.bashrc:

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

จากนั้นคุณสามารถใช้greplในบรรทัดคำสั่งที่มีการขัดแย้งใด ๆ grepที่มีอยู่สำหรับ ใช้ปุ่มลูกศรเพื่อดูส่วนท้ายของเส้นที่ยาวขึ้น ใช้qเพื่อเลิก

คำอธิบาย:

  • grepl() {: กำหนดฟังก์ชันใหม่ที่จะพร้อมใช้งานในคอนโซลทุบตี (ใหม่) ทุกเครื่อง
  • $(which grep): รับเส้นทางแบบเต็มของgrep. (Ubuntu กำหนดนามแฝงgrepที่เทียบเท่ากับgrep --color=autoเราไม่ต้องการนามแฝงนั้น แต่เป็นนามแฝงเดิมgrep)
  • --color=always: ปรับสีผลลัพธ์ ( --color=autoจากนามแฝงจะใช้ไม่ได้เนื่องจากgrepตรวจพบว่าเอาต์พุตถูกใส่ลงในไปป์และจะไม่ทำสี)
  • $@: ใส่อาร์กิวเมนต์ทั้งหมดที่กำหนดให้กับgreplฟังก์ชันที่นี่
  • less: แสดงเส้นโดยใช้ less
  • -R: แสดงสี
  • S: อย่าทำลายเส้นยาว
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.