Bir dosyadaki metni grep ve metin olan paragrafı nasıl görüntülerim?


24

Dosyadaki metin aşağıdadır:

Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

"42B" için grep yapmalı ve yukarıdaki metinden çıktısını almalıyım:

Pseudo name=Apple
Code=42B
state=fault

Bunu grep/ awk/ kullanarak nasıl başarılacağı hakkında fikri olan var mı sed?


Bu soruyu sadece "grep" ile etiketlediniz. O zaman sadece "grep" çözümleri mi arıyorsunuz? Soruda siz de awk & sed belirtin. Bu etiketleri ekleyebilir miyiz? Soruyu dün gece düzenlediğimde niyetinden emin değildim.
slm

Yanıtlar:


38

İle awk

awk -v RS='' '/42B/' file

RS=giriş kaydı ayırıcısını yeni satırdan boş satırlara değiştirir. Bir kayıttaki herhangi bir alan varsa kaydı /42B/yazdırın.

''(boş dize) POSIX'e göre boş satırları temsil etmek için kullanılan sihirli bir değerdir :

Eğer RS null, o zaman kayıt aşağıdakilerden oluşan dizileri tarafından ayrılmaktadır <newline>öncü ya da boş satır giriş başında veya sonunda boş kayıt neden olmamalıdır arka ve bir ya da daha fazla boş satırlarla, ve <newline>her bir alan ayracı olacaktır, FS'nin değeri ne olursa olsun .

Çıktı ayracı tek bir yeni satır olarak kaldığından çıktı paragrafları ayrılmayacak. Çıkış paragrafları arasında boş bir satır olduğundan emin olmak için çıkış kayıt ayırıcısını iki yeni satıra ayarlayın:

awk -v RS='' -v ORS='\n\n' '/42B/' file

1
Zarif bir çözüm için +1. Yine de dosyayı yönlendirmenize gerek yok ...
jasonwryan

parmaklar otopilottaydı.
llua

2
@jasonwryan, awk ( FILENAME) içindeki dosya adına erişmeniz gerekmiyorsa, yönlendirme kullanmak kötü amaçlı bir fikir değildir, çünkü dosya adı içeren =veya başlayan -(veya olmak -) ile ilgili sorunları önler , tutarlı hata iletileri oluşturur ve çalıştırmayı awkveya gerçekleştirmeyi önler giriş dosyası açılamıyorsa diğer yönlendirmeler.
Stéphane Chazelas

14

Verilerin yapılandırıldığını varsayalım ki istediğiniz zaman önce ve sonra her zaman bir satır olacak, grep'in -A(after) ve -B(before) anahtarlarından yararlanıp eşleşmeden önce 1 satırı ve bundan sonra 1 satırı içermesini sağlayabilirsiniz :

$ grep -A 1 -B 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

Arama teriminden önce ve sonra aynı sayı satırlarını istiyorsanız, -C(bağlam) anahtarını kullanabilirsiniz:

$ grep -C 1 "42B" sample.txt
Pseudo name=Apple
Code=42B
state=fault

Birden çok çizgiyi eşleştirirken daha sıkı olmak isterseniz, pcregrepbir deseni birden çok çizgiyle eşleştirmek için aracı kullanabilirsiniz :

$ pcregrep -M 'Pseudo.*\n.*42B.*\nstate.*' sample.txt
Pseudo name=Apple
Code=42B
state=fault

Yukarıdaki desen aşağıdaki gibi eşleşir:

  • -M - çoklu çizgiler
  • 'Pseudo.*\n.*42B.*\nstate.*'- ilk dizginin kelimenin "Pseudo"ardından başlayan, bir satırın sonuna \nkadar "42B"herhangi bir karakterin \nardından geldiği, ardından başka bir satırın ( ) sonuna kadar herhangi bir karakterin ardından gelen bir dizgenin bulunduğu bir dizge grubuyla eşleşir. "state"ardından herhangi bir karakter

5
-C(bağlam) aynıysa -Ave kısayol olarak da kullanılabilir -B.
David Baggerman

@DavidBaggerman - teşekkürler. Cevabına ekledi.
slm

Neden aşağı oy? Bu soruya cevap verir.
slm

4

Muhtemelen awk ile yapmak için benzer bir kolay yolu var, ama perl:

cat file | perl -ne 'BEGIN { $/="\n\n" }; print if $_ =~ /42B/;'

Temel olarak, dosyayı boş satırlarla ayrılmış parçalara bölmek, ardından sadece normal ifadenizle eşleşen parçaları yazdırmak diyor.


10
Bu seçenekler ve kısaltmalar kullanarak ve işe yaramaz kullanımınıcat kaybederek basitleştirilebilir ; perl -00 -ne 'print if /42B/' file
üçlü,

4

grepUnix bazı tatlar var -p"paragrafında" için bayrak. AIX'in yaptığını biliyorum .

grep -p 42B <myfile>

tam olarak orada ne istiyorsan onu yapardım. YMMV ve GNU grep bu bayrağa sahip değil.


-P bayrağına sahip olmak harika olurdu. Özellikle -v ile birlikte kullanıldığında paragrafın tamamını çıktıların dışında tutabilirsiniz.
IllvilJa,

2

Boş bir satır olmadan başka bir perl çözümü:

perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo

Örnek

% perl -00ne 'if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}' foo
Pseudo name=Apple
Code=42B
state=fault

% cat foo
Pseudo name=Apple
Code=42B
state=fault

Pseudo name=Prance
Code=43B
state=good

1
Triplee yorumunda yazdığı gibi, veya daha kısa (ve dolayısıyla daha okunabilir): perl -00 -ne 'print if /42B/' file.
mivk
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.