Eşleşen tüm dosyaları göster


71

grep --before-context 5 maçtan önce 5 satır gösterir.

Maçtan önce her şeyi göstermek istiyorum.
Yapma grep --before-context 99999999çalışacak ama çok ... profesyonel değil.

Tüm dosyalar nasıl eşleştirilir?

Yanıtlar:


95

Sed bunun için daha iyi.

Sadece yap:

sed '/PATTERN/q' FILE

Bu gibi çalışır:

Her satır için, eşleşip eşleşmediğine bakarız /PATTERN:

  • eğer evet ise, onu basar ve çıkarız.
  • Aksi takdirde yazdırırız.

Bu en etkili çözümdür, çünkü görür görmez PATTERNvazgeçer. qSed olmadan , dosyanın kalanını okumaya devam edecekti ve hiçbir şey yapamayacaktı. Büyük dosyalar için bir fark yaratabilir.

Bu numara taklit etmek için de kullanılabilir head:

sed 10q FILE

Yeni denedim, sadece dosyanın ilk satırını çıkardı ... maç 38. satırda olmasına rağmen.
Nicolas Raoul

Benim için iyi çalışıyor. Gerçek girdi ve çıktıya bir örnek verebilir misiniz? Ve çalıştırdığınız komut olduğu gibi.
Mikel

Düzenlemeden önce emrini denemiştim, öyleydi: sed '/ PATTERN / p; q' DOSYA
Nicolas Raoul

7
Desen eşleşmeli çizgiyi yazdırmak istemiyorsam ne yapmam gerekir?
tommy.carstensen

4
@ tommy.carstensen: sed '/PATTERN/Q' FILEeşleşen satırı atlayacak. Qbir GNU uzantısıdır, bu nedenle herhangi bir sed ile çalışmaz.
Alex O

37

sed grep'in işlevselliğinin çoğunu değiştirebilir.

sed -n '1,/<pattern>/ p' <file>

Bu, ilk satırdan desen eşleşene kadar yazdırmak anlamına gelir.

Birkaç aralık örneği

sed -n '/<pattern>/,$ p' <file> # from pattern to end of file
sed -n '/<pattern1>/,/<pattern2>/ p' <file> # from pattern1 to pattern2

3
Bu komut iyidir, ancak daha iyisini yapabilirsiniz. Bu şekilde tüm dosyayı okur, ancak bir eşleşme bulduğunda hemen çıkmak mümkündür.
Mikel

3
Desen eşleşmeli çizgiyi yazdırmak istemiyorsam ne yapmam gerekir?
tommy.carstensen

34

maçları yazdırabilir ve bunlara dahil:

awk '{print} /pattern/ {exit}' filename
sed '/pattern/q' filename

maç dahil BUT DEĞİL kadar yazdırın:

awk '/pattern/ {exit} {print}' filename
sed '/pattern/Q' filename

11
Qserin ama gnu özgü afaik, sed -n '/pattern/!p;//q'daha taşınabilir olurdu.
don_crissti

. @don_crissti: nasıl çalıştığını biraz merak ediyorum, gerçi ben inanıyorum: Eğer bunun iyi bir (düşünüyorum, o bir cevap yapmalıdır !yapar phatları için geçerli değil eşleşen pattern, ama sonra //qbeni ... karıştırır
JWD

2
@ don_crissti: ah, anladım - //"önceki normal ifade" anlamına geliyor ("boş dizeyle eşleşiyor " anlamına geldiğini düşündüm). Aynı çözümün daha kısa bir versiyonu olduğunu düşünüyorum: sed -n '/pattern/q;p?
JWD

jwd - gerçekten, bu daha kısa. _C
don_crissti

1

Aşağıdaki saf GNU grepyöntemleri verimli değildir.

Üç s kullanarak , dosya çubuğunda " foo " dizesinin ilk örneğine kadar olan her şeyi arayın :grep

grep -m 1 -B $(grep -n -m 1 foo bar | grep -o '^[0-9]*') foo bar

" Foo " nun son örneğiyle eşleşiyor :

grep -oPz "(?s)[^\n]*${s}.*?\n.*?foo.*?\n" bar

Not: Sonuncuyla ilgili detayları şurada bulabilirsinizgrep : Gereken çok hatlı arama için Regex (grep) .


Neden grepsadece tek bir sedçağrı yürütme meselesi olursa, 7 s (+ pcre) kullanmak istemesin : sed 'x;/./G;//!x;/foo/p;//s/.*//;x;d'??
don_crissti

@ don_crissti, sedkodunuz kendi cevabına değer görünüyor veya diğerlerinden birine eklenebilir. Re 7 greps: Çünkü grepcevap yoktu ... (artı, cevap neden olmadığını göstermeye yardımcı olur .)
agc

Bu benim kodum değil, sadece üzerine tıklayın ... Bu benim kodum olsa bile, buradaki Q cevabını vermiyor, bu yüzden cevap olarak gönderemem.
don_crissti

1

Mikel'in cevabına yukarıdakileri ekleyerek ...


Tüm satırları yazdırmak için dahil kadar değil , ilk satırı FILEiçeren PATTERN, deneyin:

  • sed '/.*PATTERN.*/{s///;q;}' FILE

Bu, deseni içeren tüm satırı eşleştirir, boş bir satırla değiştirir, ardından dosyanın geri kalanını işlemeden çıkar.


Sonrası komut dosyası:

Sonunda fazladan bir yeni satır yazdırmayı engellemenin en kolay / en net yolu (başka bir araç kullanmadan) tekrar baştan çalıştırmak ve yeni son satırı silmek oldu:

sed '/.*PATTERN.*/{s///;q;}' FILE | sed '$d'

... ve şimdi bu satırı zaten sildiğimize göre, önceki çalışmalarımız gereksiz.

sed '/PATTERN/q' FILE | sed '$d'

Glenn'in cevabı - ve benim yorumum - tek bir sedçağrı ile nasıl yapıldığını göstermektedir .
don_crissti

(Teşekkürler bunun için -. Ben AGC cevap yaptığınız yorumu gördün ama ya diğeri cevapsız ya da sadece beynim çift negatifleri sevmediği çünkü yağsız) Ben a hem de bu kullanıyordum beri tcshve bir bashtakma ad, emin olmak için gerekli Ben hem standart hem de GNU’da sed(taşınabilirlik için) çalışan nispeten özlü bir hat çözümüne sahipti ; Katkınızın çok iyi karşılandığı tüm gereklilikler. sed Çok nadiren kullanan biri olarak en önemli şartım, yıllar sonra kolayca düzenlemek veya yeniden amaçlamak istediğimde çabucak anlayabileceğim bir şeydi.
Jim Grisham,

1

Gündelik işlerde yalnızca temel araçları hatırlamayı tercih eden ve daha az zarif ve daha az verimli çözümler almaya istekli olanlar için:

head -n $(grep -n pattern filename | cut -d: -f1) filename

Bu komut bir komut dosyası içinse, daha şık (ve muhtemelen verimli) çözümler arayacağım. Bu tek seferlik bir komut veya atılma komut dosyası ise umrumda değil.


1
Güzel fikir, ama ne zaman yapacağını söyleyen üç komut.
Mikel

1
Temelleri bilmek gerçekten çok iyi. Yine de iş için doğru aracı bilmek daha iyidir.
soulmerge

Bu komut bir komut dosyası içinse, daha şık (ve muhtemelen verimli) çözümler arayacağım. Bu tek seferlik bir komutsa (veya bir fırlatma komut dosyasıysa), umrumda değil.
lesmana

0

Ayrıca aşağıdakilerden birini de kullanabilirsiniz

tac ./test | grep -B $(cat ./test | wc -l) -m 1 'pattern'|tac 

veya

tac ./test |head -n $(tac ./test | grep -n 'pattern' | cut -d: -f1 | head -n 1)|tac

veya

tac ./test |sed ':a;N;$!ba;s/\n/'"pattern"'/g' | sed 's/'"patternpattern"'/\n/g'|head -n 1|sed 's/'"pattern"'/\n/g'|tac

İlk seçenek OP'nin önerdiğine çok benzer, dosyadaki satırları sayarak bağlamdan önce yeterince satır gösterilmesini sağlar.

İkinci seçenek, ilk eşleşmenin satır numarasını arar (içteki 'başı' değiştirerek bunu da değiştirebilirsiniz) ve bu sayıdaki başı kullanır.

Son seçenek tüm yeni satırları eşleşmeyle değiştirir ve iki bitişik eşleşmeyi yeni bir satırla değiştirir. Bunun çıktısı iki eşleşme arasındaki her metin bloğu için bir çizgidir. Bundan sonra ilk satırı (ilk bloğa kadar metin bloğunu dolaşarak) eşleştirmeyi seçmek için 'head' kullanır ve her maçı yeni bir satıra çevirir. bu seçenek yalnızca dosya aşağıdaki biçimde olduğunda çalışır

pattern
texttexttext
texttexttext texttexttext
texttexttexttexttexttexttexttexttext
pattern
texttexttext
pattern 
texttexttext
texttexttexttexttexttexttexttexttext

ve diğerleri


2
Bunların nasıl çalıştığını açıklamayı düşünün, özellikle sedalttaki komut bir tür korkutucu.
strugee, 9:15

ilk seçenek OP'nin önerdiğine çok benzer, ancak filr içindeki satırları sayarak bağlamdan önce yeterli miktarda kın gösterilmesini sağlar,
user122778
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.