'Grep -q' giriş dosyasının tamamını neden tüketiyor?


23

Aşağıdaki giriş dosyasını göz önünde bulundurun:

1
2
3
4

Koşu

{ grep -q 2; cat; } < infile

hiçbir şey basmıyor. Yazdırmasını bekliyorum

3
4

Değiştirirseniz beklenen çıktıyı alabilirim

{ sed -n 2q; cat; } < infile

Neden ilk komut beklenen çıktıyı yazdırmıyor?
Bu, aranabilir bir giriş dosyasıdır ve SEÇENEKLER altındaki standarda göre :

-q
      Quiet. Nothing shall be written to the standard output, regardless of 
      matching lines. Exit with zero status if an input line is selected.

ve dahası, UYGULAMA KULLANIMI altında (benimkini vurgula):

-qSeçenek kolayca bir desen (veya dize) dosyaları bir grup var olup olmadığını belirleyen bir araç sağlar. Birkaç dosya ararken, performans iyileştirmesi sağlar ( çünkü ilk eşleşmeyi bulur bulmaz bırakabilir ) [...]

Şimdi, aynı standart başına ( Giriş bölümünde , GİRDİ DOSYALARI altında )

Standart bir yardımcı program aranabilir bir giriş dosyasını okuduğunda ve dosya sonuna ulaşmadan önce hatasız bir şekilde sona erdiğinde , yardımcı program açık dosya tanımındaki dosya ofsetinin yardımcı program tarafından işlenen son bayttan hemen sonra düzgün bir şekilde konumlandırılmasını sağlamalıdır . ..]

tail -n +2 file
(sed -n 1q; cat) < file
...

İkinci komut yalnızca dosya aranabilir olduğunda birinciye eşittir.


Neden grep -qtüm dosyayı tüketiyor?


Bu, gnu grepeğer önemliyse ( Kusalananda , aynı durumun OpenBSD'de de yapıldığını doğrulasa da )


OpenBSD'ler , merak ediyorlarsa FreeGrepgrep adlı bir çatal .
Kusalananda

Yanıtlar:


37

grep erken durmaz, ancak girişini arabelleğe alır, böylece testiniz çok kısa olur (ve evet, testim aranamadığı için kusurludur)

seq 1 10000 | (grep -q 2; cat)

sistemimde 6776'da başlıyor. GNU grep'te varsayılan olarak kullanılan 32KiB arabelleği ile eşleşir :

seq 1 6775 | wc

çıktılar

   6775    6775   32768

POSIX’in yalnızca performans iyileştirmelerinden bahsettiğini unutmayın

Birkaç dosya ararken

Bu, kısmen tek bir dosyayı okumaktan dolayı performans iyileştirmeleri için herhangi bir beklenti oluşturmuyor.


2

Bu açıkçası grepişleri hızlandırmak için yapılan tamponlamadan kaynaklanıyor . İstenilen sayıda karakter okumak ve daha fazlasını yapmak için özel olarak tasarlanmış araçlar var. Bunlardan biri expect:

{ expect -c "log_user 0; expect 2"; cat; } < infile

Bunu denemek için bir sistemim yok, ancak expectbeklenen dize ( 2) ile karşılaşıncaya kadar her şeyi yiyeceğine ve ardından girişin kalanını bırakarak sonlandırdığına inanıyorum cat.


1

Kafanı karıştırıyorsun ve kafanı karıştırıyorsun.

Sed komutu -2qiçin, ikinci satırda -nseçenek sessiz çalışmayı söylüyorsa, ikinci satırdan sonra tüm satırları elde edersiniz.

Grep komutu, eşleşen tüm satırları çıktılamak için varsayılan olarak çalışır - ancak -qseçenek stdout'a hiçbir şey çıkarmayacağını söyler. bu nedenle eğer giriş bir "2" içeriyorsa, SUCCESS'in çıkış değerine sahip olacaktır, aksi halde HATA. Bunlar işletim sisteminize ve kabuğunuza bağlıdır. Yani, tipik olarak grep işleminin çıkış değerini inceleyerek bir çizginin eşleşip eşleşmediğini söylersiniz. Bu, girişinizin test olarak bir değer içerip içermediğini bilmek istediğiniz bir boru hattında kullanışlıdır. Örneğin

if grep -q 'crash' <somelog.log ; then report_crash_via_email ; fi

Bu durumda tüm eşleşen çizgileri görmeyi gerçekten umursamıyoruz, sadece en az bir tane olup olmadığını önemsiyoruz. report_crash_via_emailSüreç / fonksiyon kapatıp gidebilir ve dosyayı yeniden açın ya da değil.

Eğer grep işleminizin "2" karakterini bulduktan sonra DURDURULMasını istiyorsanız - varsayılan olarak değil, eşleşip eşleşmediğini görmek isteyen her çizgiyi kontrol eder - bunu yapmanız gerektiğini söylemeniz gerekir. Bunun için komut satırı anahtarı -m <value>. Öyleyse durumunuz için grep -q -m1 2.


6
Cevabınız genel kullanım için yararlı bilgilerdir grepancak bu soru daha ince ve ezoterik bir şey hakkında soruyor. Sorgulanan asıl davranışı anlamak için soruyu çok hızlı okudunuz. Ayrıca, GNU grep yapar kullanıldığında durdurma arama -q(POSIX şartnamede gelen alıntı izin gibi): GNU grep devletler için adam sayfası o “herhangi bir eşleme bulunursa Çık sıfır durumu ile hemen [s]” . FWIW, sorunuzu, gelecekteki yayınları nasıl biçimlendirebileceğinizi göstermek için düzenledim. Welcom'dan Stack Exchange'e .
Anthony G - Monica

Bununla birlikte, @ user212377'nin cevabı doğrudur: bu örnekte grepdosyada '2' varsa, daha fazla ve daha az olmayan bir şey olup olmadığı sorulur. O mu değil gibi davranır sedve o noktaya kayıtları tüketir ve daha sonraki işlemler için kalan bırakın. '2' olduğunu ya da olmadığını bilinceye kadar okur, dosyayı kapatır ve sonucu döndürür.
Keith Davies

grepAslında, eğer arama dizesi dosyada mevcut değilse (sadece bütün dosyayı inceleyerek kanıtlanabilir), sadece 'bütün dosyayı tüketir' (tamponlama hususlarını dikkate almaz). Bundan daha azına rağmen, dosya okuma durur , dosya kapanır ve BAŞARI geri döner.
Keith Davies
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.