Cara memotong garis pencocokan panjang yang dikembalikan oleh grep atau ack

90

Saya ingin menjalankan ack atau grep pada file HTML yang sering memiliki baris yang sangat panjang. Saya tidak ingin melihat garis yang sangat panjang yang membungkus berulang kali. Tapi saya ingin melihat hanya bagian dari garis panjang yang mengelilingi string yang cocok dengan ekspresi reguler. Bagaimana saya bisa mendapatkannya dengan menggunakan kombinasi alat Unix?

dan
sumber
1
Apa ack? Apakah itu perintah yang Anda gunakan saat Anda tidak menyukai sesuatu? Sesuatu seperti ack file_with_long_lines | grep pattern? :-)
Alok Singhal
6
@Alok ack(dikenal sebagai ack-grepDebian) grepmenggunakan steroid. Ini juga memiliki --thppptopsi (tidak bercanda). betterthangrep.com
ZoogieZork
Terima kasih. Saya belajar sesuatu hari ini.
Alok Singhal
1
Sementara --thppptfitur agak kontroversial, keuntungan kunci tampaknya bahwa Anda dapat menggunakan Perl regexes langsung, tidak beberapa gila [[:space:]]dan karakter seperti {, [, dll berubah berarti dengan -edan -Eswitch dengan cara yang tidak mungkin untuk mengingat.
Evgeni Sergeev

Jawaban:

99

Anda dapat menggunakan opsi grep -o, mungkin dikombinasikan dengan mengubah pola Anda ".{0,10}<original pattern>.{0,10}"untuk melihat beberapa konteks di sekitarnya:

       -o, --hanya-cocok
              Perlihatkan hanya bagian dari garis yang cocok yang cocok dengan POLA.

..atau -c:

       -c, --count
              Menekan keluaran normal; sebagai gantinya mencetak jumlah baris yang cocok
              untuk setiap file masukan. Dengan opsi -v, --invert-match (lihat
              di bawah), hitung baris yang tidak cocok.
Eter
sumber
44
contoh: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud
14
Anda harus mengubah jawaban untuk menambahkan opsi -E seperti yang ditunjukkan oleh @Renaud (opsi pola diperpanjang), atau pola yang diusulkan untuk memperluas konteks tidak akan berfungsi.
kriss
Mungkin tidak terlalu perlu, tapi ini contohnya: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt cetakanqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera
Ini bekerja dengan baik; tetapi kelemahan penting adalah ketika menggunakan, misalnya, oE ".{0,20}mysearchstring.{0,20}"Anda kehilangan sorotan dari string "asli" bagian dalam yang berlawanan dengan konteks, karena semuanya menjadi pola pencarian. Ingin sekali menemukan cara untuk menyimpan beberapa konteks yang tidak disorot di sekitar hasil penelusuran, untuk pemindaian visual dan interpretasi hasil yang lebih mudah.
Aaron Wallentine
1
Oh, inilah solusi untuk masalah penyorotan yang disebabkan oleh penggunaan -oE ".{0,x}foo.{0,x}"pendekatan (di mana xjumlah karakter konteks) - tambahkan `| grep foo `sampai akhir. Berfungsi untuk solusi ack atau grep. Lebih banyak solusi juga di sini: unix.stackexchange.com/questions/163726/…
Aaron Wallentine
44

Masukkan hasil Anda melalui cut. Saya juga mempertimbangkan untuk menambahkan --cutsakelar sehingga Anda dapat mengatakan --cut=80dan hanya mendapatkan 80 kolom.

Andy Lester
sumber
8
Bagaimana jika bagian yang cocok tidak ada di 80 karakter pertama?
Eter
3
FWIW saya menambahkan | cut=c1-120grep, bekerja untuk saya (meskipun tidak tahu cara memotong teks yang cocok)
Jake Rayson
26
| cut=c1-120tidak berhasil untuk saya, saya perlu melakukannya| cut -c1-120
Ken Cochrane
1
Saya pikir @edib akurat dalam sintaks | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS
1
@AndyLester: Bagaimana dengan --no-wrapopsi yang digunakan $COLUMNS?
naught101
25

Anda dapat menggunakan lebih sedikit sebagai pager untuk ack dan memotong garis panjang: ack --pager="less -S" Ini mempertahankan garis panjang tetapi membiarkannya dalam satu baris, bukan membungkusnya. Untuk melihat lebih banyak garis, gulir ke kiri / kanan lebih sedikit dengan tombol panah.

Saya memiliki pengaturan alias berikut untuk ack untuk melakukan ini:

alias ick='ack -i --pager="less -R -S"' 
Jonah Braun
sumber
2
Harap dicatat bahwa Anda dapat meletakkan --pagerperintah itu di file ~ / .ackrc Anda, jika Anda selalu ingin menggunakannya.
Andy Lester
Ini terdengar seperti solusi terbaik sejauh ini untuk masalah ini yang sangat mengganggu saya. Saya berharap saya tahu cara menggunakan ack.
Brian Peterson
@BrianPeterson ackcukup mirip grep, hanya lebih sederhana dalam kasus yang paling umum
Aaron Wallentine
8
cut -c 1-100

mendapat karakter dari 1 hingga 100.

edib
sumber
2

Diambil dari: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

Pendekatan yang disarankan ".{0,10}<original pattern>.{0,10}"sangat bagus kecuali untuk warna highlight yang sering kacau. Saya telah membuat skrip dengan keluaran yang serupa tetapi warnanya juga dipertahankan:

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

Dengan asumsi skrip disimpan sebagai grepl, maka grepl pattern file_with_long_linesharus menampilkan baris yang cocok tetapi dengan hanya 10 karakter di sekitar string yang cocok.

xuhdev
sumber
Berfungsi, tetapi keluarannya mengikuti sampah bagi saya, seperti ini: ^ [[? 62; 9; c. Saya belum mencoba debugging karena jawaban @Jonah Braun memuaskan saya.
sondra.kinsey
1

Inilah yang saya lakukan:

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

Dalam .bash_profile saya, saya mengganti grep sehingga secara otomatis berjalan tput rmamsebelum dan tput smamsesudah, yang menonaktifkan pembungkusan dan kemudian mengaktifkannya kembali.

ognockocaten
sumber
Itu adalah alternatif yang bagus - kecuali jika pertandingan sebenarnya keluar dari layar ...
Xerus
1

masukkan deskripsi gambar di sini

Dalam situasi yang tidak biasa di mana Anda tidak dapat menggunakan -E, Anda dapat menggunakan:

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

Saya memasukkan yang berikut ke dalam saya .bashrc:

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

Anda kemudian dapat menggunakan grepldi baris perintah dengan argumen apa pun yang tersedia untuk grep. Gunakan tombol panah untuk melihat ekor garis yang lebih panjang. Menggunakanq untuk berhenti.

Penjelasan:

  • grepl() {: Tentukan fungsi baru yang akan tersedia di setiap konsol bash (baru).
  • $(which grep): Dapatkan jalur lengkap grep. (Ubuntu mendefinisikan alias untuk grepitu yang setara dengan grep --color=auto. Kami tidak menginginkan alias itu tetapi yang asli grep.)
  • --color=always: Mewarnai keluaran. ( --color=autodari alias tidak akan berfungsi karena grepmendeteksi bahwa output dimasukkan ke dalam pipa dan tidak akan mewarnainya.)
  • $@: Letakkan semua argumen yang diberikan ke greplfungsi di sini.
  • less: Menampilkan garis menggunakan less
  • -R: Tampilkan warna
  • S: Jangan putus antrean panjang
pt1
sumber