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.