Grep yalnızca arama modeliyle eşleşen kelimeleri gösterebilir mi?


685

Arama ifadesiyle eşleşen dosyalardan grep çıktısı "kelimeleri" yapmanın bir yolu var mı?

Diyelim ki, bir dizi dosyada "th" nin tüm örneklerini bulmak istersem, yapabilirim:

grep "th" *

ama çıktı gibi bir şey olacaktır (kalın benim tarafımdan);

Bazı metin dosyası: kedi oturdu mat  
Bazı-diğer metin dosyası: Hızlı kahverengi tilki  
yet-another-text-file: Umarım bu iyice açıklar 

Ne aynı arama kullanarak, çıktı istiyorum:

the
the
the
this
thoroughly

Bu grep kullanmak mümkün mü? Veya başka bir araç kombinasyonu mu kullanıyorsunuz?


2
Dan Midwood çözümü mükemmel çalışıyor ve krediyi hak ediyor.
hakish

Satırları değiştirmeden eşleşen kelimeleri yazmanın bir yolu var mı? Eşleşen dize aynı satırda mı kalmalı?
Linguist

Yanıtlar:


956

Grep -o'yu deneyin

grep -oh "\w*th\w*" *

Düzenleme: Phil'in yorumundan eşleştirme

Gönderen docs :

-h, --no-filename
    Suppress the prefixing of file names on output. This is the default
    when there is only  one  file  (or only standard input) to search.
-o, --only-matching
    Print  only  the matched (non-empty) parts of a matching line,
    with each such part on a separate output line.

9
@ user181548, grep -o seçeneği yalnızca GNU grep için çalışır. GNU grep kullanmıyorsanız, sizin için işe yaramayabilir.
ksinkar

5
@ABB Eşleşen dosyanın adını görüntülemek isteyip istemediğinize bağlıdır. Hangi koşullar altında görüntülenip görüntülenmediğinden emin değilim, ancak birkaç dizinde grep kullandığımda, eşleşen tüm dosyalar için tam dosya yolunu görüntülediğini biliyorum, oysa -h ile hangi dosyanın olduğuna dair herhangi bir spesifikasyon olmadan eşleşen kelimeler. Bu nedenle, orijinal soruyu eşleştirmek için, bazı durumlarda bunun gerekli olduğunu düşünüyorum.
LokMac

1
Ne "\w*th\w*" *anlama geldiğine ilişkin bir açıklamaya ihtiyacım vardı , bu yüzden göndereceğimi düşündüm. \w[_ [: alnum:]] olduğundan, bu temelde 'th' içeren herhangi bir "kelime" ile eşleşir (çünkü \wboşluk içermez). Alıntılanan bölümden sonraki * dosyalar için bir
globtur

1
\wgenellikle taşınabilir değildir grep -E; düzgün taşınabilirlik için [[:alnum:]]bunun yerine POSIX karakter sınıfı adını kullanın (veya [_[:alnum:]]alt çizgiyi gerçekten istiyorsanız; veya grep -Pplatformunuzda buna sahip olup olmadığını deneyin ).
tripleee

@ABB OP tarafından gösterilen istenen çıktı göz önüne alındığında -h, tamamen gerekli olduğunu söyleyebilirim ..?
El Ronnoco

81

Çapraz dağıtım güvenli cevabı (windows minGW dahil?)

grep -h "[[:alpha:]]*th[[:alpha:]]*" 'filename' | tr ' ' '\n' | grep -h "[[:alpha:]]*th[[:alpha:]]*"

-O seçeneğini içermeyen grep'in eski sürümlerini (2.4.2 gibi) kullanıyorsanız. Yukarıdakileri kullanın. Başka aşağıdaki sürümü korumak için daha basit kullanın.

Linux çapraz dağıtım güvenli cevabı

grep -oh "[[:alpha:]]*th[[:alpha:]]*" 'filename'

Özetler için -ohsadece o zaman aram hangi kelime veya düzenli ifade vim / etc iş ... için normal ifade beklenir nasıl gibi düzenli ifade dosya içeriğine maçları (ve dosya adını) verir, kadardır sen! Perl sözdiziminde değil, POSIX'te kaldığınız sürece (aşağıya bakın)

Grep kılavuzundan daha fazlası

-o      Print each match, but only the match, not the entire line.
-h      Never print filename headers (i.e. filenames) with output lines.
-w      The expression is searched for as a word (as if surrounded by
         `[[:<:]]' and `[[:>:]]';

Orijinal cevabın herkes için işe yaramamasının nedeni

Kullanımı \w"perl" sözdizimi olarak platformdan platforma değişir. Bu nedenle, POSIX karakter sınıflarıyla çalışmak için sınırlı olan bu grep kurulumu [[:alpha:]]perl eşdeğerini değil kullanır \w. Daha fazla bilgi için normal ifade hakkındaki Wikipedia sayfasına bakın

Sonuç olarak, yukarıdaki POSIX cevabı, grep için platformdan (orijinal olan) bağımsız olarak çok daha güvenilir olacaktır

-O seçeneği olmayan grep desteğine gelince, ilk grep ilgili satırları çıkarır, tr boşlukları yeni satırlara böler, son grep filtreleri sadece ilgili satırlar için.

(PS: Şimdiye kadar çoğu platform biliyorum, \ w .... için yamalı olurdu ama her zaman geride kalanlar vardır)

@AdamRosenfield yanıtından "-o" geçici çözümü için kredi


1
Peki ya sadece GNU grep'te çalışmak (ksinkar'ın kabul edilen cevabın yorumunda belirtildiği gibi)?
Brilliand

@Brilliand hmm, im '-o' desteklemeyen bir linux uygulaması bulmakta sorun yaşıyorum, eğer kontrol etmek için hangi platformu biliyorum ben etrafında bir iş arayabilirsiniz.
PicoCreator

@pico Bu -oseçenek, git paketiyle (minGW?) yüklenen Windows grep'te yoktur: "c:\Program Files (x86)\Git\bin\grep" --version grep (GNU grep) 2.4.2
Bruce Peterson

@BrucePeterson -o için AdamRosenfield geçici çözümüne ekledim: Windows git tr / sed ve sürümünü içerip içermediğini kontrol etmeme yardım et. Bu geçici çözümün çalışıp çalışmadığını kontrol edebilirim
PicoCreator

@pico: GIT için: GNU sed sürüm 4.2.1, tr (GNU textutils) 2.0
Bruce Peterson

46

Sandığından daha basit. Bunu dene:

egrep -wo 'th.[a-z]*' filename.txt #### (Case Sensitive)

egrep -iwo 'th.[a-z]*' filename.txt  ### (Case Insensitive)

Nerede,

 egrep: Grep will work with extended regular expression.
 w    : Matches only word/words instead of substring.
 o    : Display only matched pattern instead of whole line.
 i    : If u want to ignore case sensitivity.

2
Bu, 4+ yıl öncesindeki mevcut cevaplara bir şey eklemiyor gibi görünüyor.
tripleee

3
@tripleee Bu yaklaşım gönderdi benim yaklaşım daha iyi ve basit buldum.
Abhinandan prasad

42

Boşlukları yeni satırlara ve ardından grep'e çevirebilirsiniz, örneğin:

cat * | tr ' ' '\n' | grep th

18
gerek yok kedi. tr '' '\ n' <dosya | grep th. Büyük dosyalar için yavaş.
ghostdog74

Bu işe yaramadı. Çıktı yine de dosya adını ve eşleşmeyi içeren dosyadaki tüm satırı içeriyordu. Her neyse, sunulan diğer çözümlerden biri çalıştı. Yine de giriş için teşekkürler.
Neil Baldwin

@ ghostdog74: iyi bir nokta, ancak dosyadan daha fazlasına sahipseniz, kedi kullanmanız gerekir. @Neil Baldwin: Doğru yazdığınızdan emin misiniz? Yalnızca bir girdi dosyası (bu durumda stdin) olduğunda, grep dosya adını yazdırmaz.
Adam Rosenfield

@Adam - evet, özür dilerim Adam, bir dosya ile çalışıyor ama birden fazla değil.
Neil Baldwin

4
@ ghostdog74 Yavaş kısmı nedeniyle tr, önce yapabilirdi grep, bu yüzden trsadece eşleşen satırlara uygulanır:grep th filename | tr ' ' '\n' | grep th
Carcamano

37

Sadece awk, alet kombinasyonuna gerek yok.

# awk '{for(i=1;i<=NF;i++){if($i~/^th/){print $i}}}' file
the
the
the
this
thoroughly

8
@AjeetGanga iyi, isminde
Daerdemandt

11

Yalnızca eşleşen ve perl için grep komutu

grep -o -P 'th.*? ' filename

3
Sadece eşleşen grubun görüntülenmesine ne dersiniz?
Bishwas Mishra

Bu işe yaramıyor; yalnızca thjoker karakterin mümkün olan en kısa tekrarını talep ettiğiniz için bulacaktır .
tripleee

@tripleee - bu sorun olmayacak, çünkü normal ifadenin sonunda bir boşluk var. Ancak, arkasından boşluk olmayan sözcükleri, örneğin satırların uçlarını, özleyecektir.
Ken Williams

8

Ben awk sözdizimi hatırlamak zor memnun değildi ama bunu yapmak için bir yardımcı programı kullanma fikrini sevdim.

Ack (veya Ubuntu kullanıyorsanız ack-grep) bunu kolayca yapabilir:

# ack-grep -ho "\bth.*?\b" *

the
the
the
this
thoroughly

-H bayrağını atlarsanız şunları elde edersiniz:

# ack-grep -o "\bth.*?\b" *

some-other-text-file
1:the

some-text-file
1:the
the

yet-another-text-file
1:this
thoroughly

Bir bonus olarak, --outputbulduğum en kolay sözdizimiyle daha karmaşık aramalar yapmak için bayrağı kullanabilirsiniz :

# echo "bug: 1, id: 5, time: 12/27/2010" > test-file
# ack-grep -ho "bug: (\d*), id: (\d*), time: (.*)" --output '$1, $2, $3' test-file

1, 5, 12/27/2010


4

"İcon-" ile başlayan tüm kelimeleri aramak için aşağıdaki komut mükemmel çalışır. Ben burada gk benzer ama daha iyi seçenekler ve güzel biçimlendirme ile Ack kullanıyorum .

ack -oh --type=html "\w*icon-\w*" | sort | uniq

3

Ayrıca pcregrep'i de deneyebilirsiniz . Ayrıca grep'te bir -wseçenek var , ancak bazı durumlarda beklendiği gibi çalışmıyor.

Gönderen Vikipedi :

cat fruitlist.txt
apple
apples
pineapple
apple-
apple-fruit
fruit-apple

grep -w apple fruitlist.txt
apple
apple-
apple-fruit
fruit-apple

3

Ben grep / pattern regex ve çıktı olarak "eşleşen desen" arıyor benzer bir sorun vardı.

Sonunda -rep seçeneği ile egrep (grep -e veya -G'deki aynı regex bana egrep'in aynı sonucunu vermedi) kullandım

yani, bunun benzer bir şey olabileceğini düşünüyorum (ben normal regex ustası değilim):

egrep -o "the*|this{1}|thoroughly{1}" filename

İşe yaramayan {1}niceleyiciler düşürülmelidir. Veya tutarlı olmak, t{1}h{1}e{1}vb.
İstiyorsanız

aynı çizgiyle yazdırabilir mi?
凡 凡

-1

Grep çıktınızı Perl'e şu şekilde bağlayabilirsiniz:

grep "th" * | perl -n -e'while(/(\w*th\w*)/g) {print "$1\n"}'

9
doğru sonucu vermez. ayrıca, Perl kullanılıyorsa, grep kullanmaya gerek yoktur. Perl'de her şeyi yapın.
ghostdog74

Hatayı gösterdiğin için teşekkürler, ghostdog74. Sadece ilk kelimeyi değil, satırdaki tüm kelimeleri yazdırmak için değiştirdim.

Dediğim gibi, grep gerekli değil. perl -n -e'while (/ (\ s + th \ w *) / g) {print "$ 1 \ n"} 'file
ghostdog74

7
sana bağlı. sadece bir noktayı gösteriyorum. Gerekli değilse, yapma. bu ekstra "|" size bir işlem daha mal olacak.
ghostdog74

1
Perl 5.10 veya sonrasında: perl -nE '@ = = (normal ifade) / ig; "\ n", @a 'katılın
Profesör Photon

-1
$ grep -w

Grep man sayfasından alıntı:

-w: Yalnızca tam sözcükleri oluşturan eşleşmeleri içeren satırları seçin. Test, eşleşen alt dizenin ya satırın başında olması ya da öncesinde sözcük olmayan bir kurucu karakterden oluşması gerektiğidir.


1
Bu yine de eşleşmeyi içeren tüm satırı yazdıracaktır. Gerçek eşleşmeyi sınırlar, böylece theartık "bunlar" veya "banyo" ile eşleşmez.
üçlü

-6

ripgrep

İşte örnek ripgrep:

rg -o "(\w+)?th(\w+)?"

Eşleşen tüm kelimelerle eşleşir th.

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.