2012-01-27 12 views
8

Başlangıcını kullanma Sıklıkla büyük bir csv dosyasının başlığını almak ve geri kalanını belirli bir giriş için aramak istiyorum. Bunu aşağıdaki gibi yaparım.Stdin'i bir dosyadan almak neden bir borudan almaktan farklıdır?

$ (head -1; grep mike) < tmp.csv 
name,age,favourite colour 
mike,38,blue 

Ama kedi veya çalışmıyor başka komuta girdi alarak - grep dosyanın geri kalanını geçti geçmez görünüyor.

$ cat tmp.csv | (head -1; grep mike) 
name,age,favourite colour 

Bu iki durumda neden farklı davranışlar var?

+0

wc -l test.txt' -output-> 3 '(kafa -1>/dev/null; wc -l) 2. – danihp

+0

Bazı teorilerim var ama bunu 3.2.248 (Darwin) ile yeniden üretemiyorum. Hangi sürümü kullanıyorsunuz? –

+0

Bu, bir rhel 5.6 makinesinde, GNU bash, 3.2.25 (1) -release (x86_64-redhat-linux-gnu) sürümüdür. – tlrrd

cevap

7

fark borusundan okuma ve bir dosyadan okuma arasında olduğunu yapabilirsiniz lseek bir dosya üzerinde, ancak bir boruya. (strace aracılığıyla görüldüğü gibi) davranışı, bash değil head'dan geliyormuş gibi görünür. head bir arabellek okuyacak ve uygun satır sayısını bulacak, daha sonra lseek son çıktı satırının sona erdiği noktaya geri dönecek ve bu şekilde dosya tanıtıcısını açık bırakacaktır. Yukarıdaki gibi, bu bir dosya okuyorsa, ancak bir borudan okuyorsa işe yaramaz.

diğer durumundan başka bir şey düşünmüyorum, bu davranış head içinde yaptığınız şeyden daha mantıklı, ama işte burada. Her gün yeni bir şeyler öğrenin, size şunu söylerim:

+0

+1 Harika cevap, ama bu sadece delice. – cmbuckley

0

Bu ürünü güvenilir bir şekilde 3.2.248 ile yeniden oluşturamıyorum. İkisi de başarılı veya başarısız. Ancak, başarısızlıkların altında yatan sebep, dosyanın ne kadar büyük olduğudur. Bir arabellek (sisteme bağlı olarak 4k-64k) okur ve boruyu aşağıya uzatır. head tüm arabelleği tüketir ve sonra çıkar. grep, daha sonra tampon boyutundan sonra dosyaya erişebilir. Sistemimde, piponuzu dosyaya tek bir tampondan daha fazla grep şeyden daha fazla kullanabilirim (böylece uzun bir dosyanın sonunda bir şeyler yapabilirim, ancak head'u kullandıktan sonra).

Daha sonraki bash sürümleri, hile çalışmanıza izin vermek için < işlecini (ancak cat değil) en iyi duruma getirebilir, ancak bunun desteklenen bir davranış olduğuna inanmıyorum.

+1

Hayır, kesinlikle boyut değil. http://sprunge.us/SXCO –

3

Çok garip. Sen, bu belgesiz davranışı kullanan artık şöyle bir şey kullanmamalısınız:

sed -n '1p;/mike/p' tmp.csv 
+2

Belgesiz bir davranış değil. Herşey beklendiği gibi çalışır (bkz. Kötü ottos cevabı). Bu sadece kötü bir uygulamadır - ikinci (standart) birincinin davranışına bağlı olduğundan, ortak standart girdiden veri okumak için '(command1; command2)' yapısını kullanmak. Yani sen de emrinde haklısın. –

İlgili konular