it-swarm-tr.com

Grep'i sadece eşleşenlerle değil, tüm satırları çıkarmaya ikna et

Diyelim ki şu dosyaya sahibim:

$ 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

Varsayılan olarak, grep arama terimini içeren her satırı döndürür:

$ grep test test

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

--color parametresini grep, satırın arama ifadesiyle eşleşen bölümünü vurgulamasını sağlar, ancak yine de yalnızca ifadeyi içeren satırları döndürür. Kaynak dosyadaki her satırı çıkarmak için grep almanın bir yolu var mı, ancak eşleşmeleri vurgulayın mı?

Bunu başarmak için şu anki korkunç kesmek (en azından eşleşmesi olmayan 10000'den fazla ardışık satır içermeyen dosyalarda):

$ grep -B 9999 -A 9999 test test

Screenshot of the two commands

grep bunu başaramazsa, aynı işlevselliği sunan başka bir komut satırı aracı var mı? ack ile uğraştım, ama bunun için de bir seçenek yok gibi görünüyor.

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

Burada yaptığımız $ paterni ve test paterni, açıkçası $ renklendirecek bir şey yok, bu yüzden sadece test desen renk alır. -E sadece genişletilmiş normal ifade eşleşmesini açar.

Bunun gibi kolayca bir işlev oluşturabilirsiniz:

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

ubuntu ve Debian için ack yerine ack-grep kullanın

ack-grep --passthru --color string file

Bunu grep ile portatif olarak ve yapmanın başka bir yolu (iki kullanmanın yanı sıra) kabul edilen cevapta olduğu gibi değişimli regex'ler null paterni (ve sırasıyla null dizesi) yoluyla olur.
Hem -E Hem de -F Anahtarlarıyla eşit derecede iyi çalışmalıdır, standart başına :

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

ve

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

Yani bu sadece koşma meselesi

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

ve sırasıyla

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

Bu tür şeyler için kullandığım aşağıdaki işlevi var:

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

Dahili olarak çirkin görünüyor, Güzel ve kullanımı kolay, şöyle:

cat some_file.txt | highlight some_Word

veya biraz daha gerçek dünya örneği için:

tail -f console.log | highlight ERROR

1 Ve 31 Ve 43 Öğelerini değiştirdikten sonra renkleri istediğiniz gibi değiştirebilirsiniz (grep ile zor olabilir - emin değilim) \e[). Kullanılacak kodlartümü bitti yer , ancak işte hızlı bir giriş: 1 metin metnini, 31 kırmızı yapar ve 43 sarı bir arka plan verir. 32 Veya 33 Farklı renkler olabilir ve 44 Veya 45 Farklı arka planlar olur: fikri anlarsınız. Çok eğimliyseniz bile yanıp sönmeyi (5 İle) yapabilirsiniz.

Bu özel Perl modülleri kullanmaz ve Perl neredeyse her yerde bulunur, bu yüzden hemen hemen her yerde çalışmasını beklerim. Grep çözümü çok zekidir, ancak grep üzerindeki --color anahtarı her yerde mevcut değildir. Örneğin, bu çözümü bash çalışan bir Solaris kutusunda ve başka bir çalışan ksh'da ve zsh çalıştıran yerel Mac OS X makinemde denedim. Hepsi iyi çalıştı. Ancak Solaris grep --color Çözümünü boğdu.

Ayrıca, ack harika ve henüz keşfetmemiş herkese tavsiye ederim, ancak üzerinde çalıştığım birçok sunucudan birkaçını yüklerken bazı sorunlar yaşadım. (Nedenini unuttum: Gerekli Perl modülleriyle ilgili olduğunu düşünüyorum.)

Hiç bir Unix kutusu üzerinde çalıştığımı sanmıyorum Perl yüklü (gömülü tip sistemler, Linksys yönlendiriciler vb. hariç) bunun evrensel olarak kullanılabilir bir çözüm olduğunu söyleyebilirim.

11
iconoclast

Grep kullanmak yerine Daha Az'ı kullanabilirsiniz:

less file

Bunun gibi ara: /pattern Enter

Bu irade:

  1. eşleşen ilk satıra git
  2. oradan başlayarak her satırı çıktılar
  3. tüm eşleşmeleri vurgula

Bir sonraki eşleşen satıra geçmek için: n

Önceki eşleşen satıra geçmek için: N

Vurgulamayı değiştirmek için: Esc u

İsterseniz vurgulama rengi değerini de değiştirebilirsiniz.

3
Steven Penny

Deneyebilirsin:

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

Ancak çok taşınabilir değil ve Perl takılı olsa bile, başka bir modül indirmeniz gerekebilir. Buna ek olarak, yalnızca arama sözcüğünü değil tüm satırı renklendirir.

2
gvkv

Şimdiye kadar verilen cevapların hiçbiri taşınabilir bir çözüm sunmamaktadır.

İşte taşınabilir1 Kabuk işlevi I zaten yayınlanmıştır , standart olmayan araçlar veya Perl, ack, ggrep, gsed, bash ve benzerleri ancak yalnızca bir POSIX Kabuğuna ve POSIX zorunlu yardımcı programlarına _ ihtiyaç duyuyor sed ve printf:

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

Bu şekilde kullanabilirsiniz:

grepc string_to_search [file ...]

Vurgu rengi, sed komut bağımsız değişkeninde şu kodlardan biri kullanılarak ayarlanabilir (32m burada yeşil renktedir):

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

1 Terminaliniz ANSI renkleri desteklediği sürece dizilerden kaçar.

2
jlliagre

ripgrep

ripgrep ile --passthru parametre:

rg --passthru pattern file.txt

En hızlı selamlama araçları 'dan biridir, çünkü aramayı çok hızlı yapmak için sonlu otomata, SIMD ve agresif değişmez optimizasyonları kullanan Rust'un regex motor üzerine inşa edilmiştir.

--passthru - Hem eşleşen hem de eşleşmeyen satırları yazdırın.

Benzer bir etki elde etmenin başka bir yolu, deseninizi boş dizeyle eşleşecek şekilde değiştirmektir. Örneğin, rg foo sonra rg "^|foo" bunun yerine, aranan her dosyadaki her satırı yayar, ancak yalnızca foo olayları vurgulanır. Bu bayrak, kalıbı değiştirmeye gerek kalmadan aynı davranışı etkinleştirir.

2
kenorb

GNU grep için bunu yapmanın çok daha kolay bir yolu var ama taşınabilir olduğunu düşünmüyorum (yani, BSD grep):

Bir boruda:

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

Bir dosyada:

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

Kredi Cyrus'un cevabına gider.

1
Erik Nomitch

Bir sed sürümü, hem bash hem de ash üzerinde çalışır.

#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 grep istedi ve bu da TAVSİYE EDİYORUM; ancak sed ile ilgili bir sorunu çözmek için çok çalıştıktan sonra, kayıt için burada basit bir çözüm var:

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

veya

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

main kırmızıya boyayacak.

  • \E[31m: Kırmızı renk başlangıç ​​sırası
  • \E[0m: Bitmiş renk işareti
  • &: Eşleşen desen
  • /g: Yalnızca ilk satırda değil, bir satırdaki tüm kelimeler
  • $'string' Çıkış karakterleri yorumlanmış bash dizeleridir

grep ile ilgili olarak, ^ (Satır sonu) yerine $ (Satır başı) kullanılarak da çalışır. Misal:

egrep "^|main" testt.c

Ve sadece bu çılgın takma adı göstermek için ÖNERMİYORUZ, hatta açık tırnaklara izin verebilirsiniz:

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

bütün iş! :) Alıntıyı kapatmayı unutursanız endişelenmeyin, bash sizi "devam eden çizgi karakteri" ile hatırlayacaktır.

0
Dr Beco