Grep komutu sonucunda alınan her satırı işleme


152

Aşağıdaki gibi grep komutunu çalıştırdıktan sonra bir dosyadan alınan satırların bir dizi var :

var=`grep xyz abc.txt`

Diyelim ki sonuç olarak xyz'den oluşan 10 satırım var.

Şimdi grep komutunun bir sonucu olarak aldığım her satırı işlemem gerekiyor. Bunun için nasıl ilerlerim?


6
Buradaki cevapların hiçbiri grep -obu tür şeylerin gücünden bahsetmiyor . -oBayrak geri verecek tek çıktı satır başına bir eşleme ile, kibrit metni. (Kapsamlı değildir, bu yüzden echo aaa |grep 'a*'size sadece "aaa" verir ve "", "a" ve "aa" adlı üç kısmi eşleşmeyi atlar)
Adam Katz

Yanıtlar:


269

Kolay yollardan biri, çıktıyı bir değişkende saklamak değil, bir while / read döngüsü ile doğrudan üzerinden yinelemektir.

Gibi bir şey:

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

Bu şemada tam olarak neyin peşinde olduğunuza bağlı olarak varyasyonlar var.

Döngü içindeki değişkenleri değiştirmeniz gerekiyorsa (ve bu değişikliğin dışında görünür olması gerekiyorsa), fedorqui'nin cevabında belirtildiği gibi işlem ikamesini kullanabilirsiniz :

while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)

xyz ile çizgi yoksa?
XYZ_Linux

Sonra hiçbir şey olmaz, döngü çalışmaz.
Mat

13
Bu yöntemin problemi, (borudan dolayı), döngü içindeki her şeyin bir alt kabukta olmasıdır, bu nedenle döngü sırasında döngü dışında tanımlanan değişkenleri döngüden sonra kullanılabilir hale getirmez!
David Doria

3
@David: Endişenizi gidermek için bir alternatif sunmuştur. (fedorqui zaten bunu ele almıştı.)
Mat

Son çıkış satırı yeni satırla sonlandırılmayan komutlar için aşağıdakilere ihtiyacınız vardır: while read p || [[ -n $p ]]; do ...( stackoverflow.com/questions/1521462/… ' dan ödünç alındı )
Ohad Schneider

21

İşlem ikamesi denilen komut kullanılarak komutun while readsonucuyla beslenecek aşağıdaki döngüyü yapabilirsiniz grep:

while IFS= read -r result
do
    #whatever with value $result
done < <(grep "xyz" abc.txt)

Bu şekilde, sonucu bir değişkende saklamak zorunda kalmazsınız, ancak çıktısını doğrudan döngüye "enjekte eder".


Kullanımını Not IFS=ve read -rBashFAQ / 001 önerilere göre: Bir dosyayı (veri akışı, değişken) çizgi-by-line (ve / veya bu alanda bazında alanda) okuyabilir nasıl? :

Okuma için -r seçeneği ters eğik çizgi yorumlamasını önler (genellikle ters eğik çizgi yeni satır çifti olarak kullanılır, birden çok satıra devam etmek veya sınırlayıcılardan kaçmak için). Bu seçenek kullanılmazsa, girişteki çıkışsız ters eğik çizgiler atılır. Hemen her zaman okuma ile -r seçeneğini kullanmalısınız.

Yukarıdaki senaryoda IFS = ön ve arka boşlukların kırpılmasını önler. Bu efekti istiyorsanız kaldırın.

İşlem ikamesi ile ilgili olarak, bash hackerlar sayfasında açıklanmaktadır :

İşlem ikamesi, bir işlemin giriş veya çıkışının (bazı komut dizileri) geçici bir dosya olarak göründüğü bir yönlendirme şeklidir.


Tamam, forsürümü gördüm . Stackoverflow.com/a/14588210/1983854'teki"${$(grep xyz abc.txt)[@]}" gibi bir döngü yapmaya çalıştım, ancak yapamadı. Bu yüzden sadece ilk sürümü terk ediyorum.
fedorqui 'SO' zarar vermeyi durdur

1
Bir komut ikamesine parametre genişletmesi uygulayamazsınız ( zshbu tür yuvalamanın muhtemelen işe yaradığı yerlerde kullanmıyorsanız ).
chepner

Bu deyimle ilgili olası bir sorun, döngü içindeki herhangi bir şey standart girdiden okumaya çalışırsa, dosyanın bir parçasını alacak olmasıdır. Bu olasılığı önlemek için, dosyayı stdin yerine dosya tanıtıcısı 3 ile göndermek istiyorum. Sadece kullanın while IFS= read -r result <&3vedone 3< <(grep ...
Gordon Davisson

8

Burada grep + yerine başka bir şey yerine awk kullanmanızı öneririm.

awk '$0~/xyz/{ //your code goes here}' abc.txt


1
Bulunan hattın tamamına nasıl referans verirsiniz //your code goes here?
user857990

2
@ user857990 Satırın tamamı AWK'da 0 $ olarak temsil edilir.
Julien Grenier

2

--Line arabelleğe alınmış grep seçeneği ile herhangi bir yineleme olmadan:

your_command | grep --line-buffered "your search"

Symfony PHP Framework yönlendirici hata ayıklama komutu çıkışıyla gerçek hayattan örnek "api" ile ilgili tüm rotaları grep:

php bin/console d:r | grep --line-buffered "api"

tail -f some.log
Komutunuz

0

Genellikle işlemin sırası önemli değildir. GNU Paralel bu durum için yapılmıştır:

grep xyz abc.txt | parallel echo do stuff to {}

İşleminiz daha çok şöyle ise:

grep xyz abc.txt | myprogram_reading_from_stdin

ve myprogramyavaşsa o zaman çalıştırabilirsiniz:

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

0

Bir while / read döngüsü ile grep sonuçları üzerinde yineleme yapın. Sevmek:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done

0

Tek astar arayanlar için:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done
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.