Maçtan önce ve sonra Grep karakterleri?


144

Bunu kullanarak:

grep -A1 -B1 "test_pattern" file

dosyadaki eşleşen desenden önce ve sonra bir satır oluşturur. Satırları değil, belirli sayıda karakteri görüntülemenin bir yolu var mı?

Dosyamdaki çizgiler oldukça büyük, bu yüzden tüm satırı yazdırmakla ilgilenmiyorum, sadece eşleşmeyi bağlamda gözlemliyorum. Bunu nasıl yapacağımıza dair herhangi bir tavsiye var mı?


Yanıtlar:


184

3 karakter önce ve 4 karakter sonra

$> echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}'
23_string_and

5
Küçük miktarlardaki veriler için iyi bir yanıt, ancak 100'den fazla karakterle eşleştiğinizde yavaşlamaya başlar - örneğin dev xml dosyamda {1,200} öncesi ve sonrası istiyorum ve kullanmak çok yavaş.
Benubird

3
@Amit_g'nin awk sürümü çok daha hızlı.
ssobczak

6
Mac OSX'te mevcut değildir, bu yüzden bu yaygın olarak bulunmayan bir çözüm değildir. -E sürümü (aşağıda listelenmiştir) daha iyi bir çözümdür. -P nedir? Okumaya devam edin ... -P, --perl-regexp PATTERN'yi Perl düzenli ifadesi olarak yorumlama (PCRE, aşağıya bakınız). Bu son derece deneyseldir ve grep -P uygulanmamış özellikleri uyarabilir.
Xofo

2
OSX'te: brew install homebrew/dupes/grepile yükleyin ve olarak çalıştırın ggrep.
kenorb

1
@Benubird tarafından ima edildiği gibi, bu, maç hedefi için orta derecede geniş çevresi olan büyük dosyalar için performans açısından imkansız olacaktır.
matanster

113
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

Bu, deseninizden önce ve sonra 5 karaktere kadar eşleşir. -O anahtarı grep'e yalnızca eşleşmeyi göstermesini ve -E'ye genişletilmiş normal ifade kullanmasını söyler. Alıntıları ifadenizin etrafına koyduğunuzdan emin olun, aksi takdirde kabuk tarafından yorumlanabilir.


1
İyi cevap, {} çok {0,255}çalışır {0,256}verir uzunluğunda 2 ^ 8-1 ile sınırlanmış ilginçgrep: invalid repetition count(s)
CodeMonkey

Eşleşen karakter sayısını (5 -> 25 -> 50) artırdığımda bu önemli ölçüde daha az performans gösteriyor gibi görünüyor, neden?
Adam Hughes

37

Kullanabilirsin

awk '/test_pattern/ {
    match($0, /test_pattern/); print substr($0, RSTART - 10, RLENGTH + 20);
}' file

2
Biraz daha büyük dosyalarla bile güzel çalışıyor
Touko

4
satır başına birden fazla eşleşme bulmak için bunu nasıl kullanabilirsiniz?
koox00

1
Kıvrımlı ayraçlı çiftlerdeki ilk sayının önemi nedir? "Grep -E -o" içindeki 0'lar gibi. {0,5} test_pattern. {0,5} "test.txt"?
Lew Rockwell Fan

Gerçekten daha hızlı ama @ ekse'nin yanıtı kadar doğru değil.
Abdollah

24

Yani, şöyle:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

?

Bu, her iki yüzüne de yirmi karakter basacaktır test_pattern. \{0,20\}Notasyonu gibidir *, ancak belirtir yirmi tekrarlar için sıfır yerine sıfır veya daha uzun -oziyade tüm çizgi daha sadece maçı kendisi göstermeye söylüyor.


Bu komut benim için çalışmıyor:grep: Invalid content of \{\}
Alexander Pravdin

0

İle gawk, eşleştirme işlevini kullanabilirsiniz:

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

Tamam ise perl, daha esnek bir çözüm: Aşağıdaki, desenden önce üç karakter, ardından gerçek desen ve ardından desenden 5 karakter basacaktır.

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

Bu, yalnızca karakterler yerine sözcüklere de uygulanabilir. Takip etmek, gerçek eşleme dizesinden önce bir kelime yazdıracaktır.

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

Kalıptan sonra bir kelime yazdırılır:

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

Aşağıda, desenden önce bir kelime, ardından gerçek kelime ve sonra desenden sonra bir kelime yazdırılacaktır:

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

0

Vurgulamak için regexp grep + vurgulamak için ikinci grep kullanabilirsiniz

echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}' | grep string

23_string_and

resim açıklamasını buraya girin


0

Bu şifreli komut değiştiricileri asla hatırlayamayacağım, bu yüzden üst yanıtı aldım ve dosyamdaki bir işleve dönüştürdüm ~/.bashrc:


cgrep() {
    # For files that are arrays 10's of thousands of characters print.
    # Use cpgrep to print 30 characters before and after search patttern.
    if [ $# -eq 2 ] ; then
        # Format was 'cgrep "search string" /path/to/filename'
        grep -o -P ".{0,30}$1.{0,30}" "$2"
    else
        # Format was 'cat /path/to/filename | cgrep "search string"
        grep -o -P ".{0,30}$1.{0,30}"
    fi
} # cgrep()

İşte işte böyle görünüyor:

$ ll /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

-rw-r--r-- 1 rick rick 25780 Jul  3 19:05 /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

$ cat /tmp/rick/scp.Mf7UdS/Mf7UdS.Source | cgrep "Link to iconic"

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

$ cgrep "Link to iconic" /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

Söz konusu dosya sürekli bir 25K satırdır ve düzenli olarak aradığınızı bulmak umutsuzdur grep.

cgrepParalellik grepmetodu olarak adlandırmanın iki farklı yoluna dikkat edin .

"$ 2" ayarının yalnızca 4 satır kod kaydedecek şekilde ayarlandığı zaman geçtiği fonksiyonu oluşturmanın "daha şık" bir yolu vardır. Yine de kullanışlı değil. Gibi bir şey ${parm2} $parm2. Eğer bulursam, fonksiyonu ve bu cevabı gözden geçireceğim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.