Dosya içeriği yalnızca ilk satır belirli bir kalıpla eşleşirse nasıl yazdırılır?


11

Bir komut dosyası yazıyorum, dosyanın ilk satırının belirli bir desenle eşleşip eşleşmediğini ve dosyayı yazdırıp yazdırmadığını kontrol etmek istiyorum. Bunu nasıl başarabilirim?

Kalıbı nasıl kontrol ederim? Desen kontrol etmek için bir yol var mı ve çıkış dayalı bir şey yapmak ..

EDIT: Lütfen şu soruya bir göz atın: /programming/5536018/how-to-get-match-regex-pattern-using-awk-from-file

Böyle bir şey istiyorum, ama hiçbiri benim için çalışmadı. Temelde ilk satırın bir normal ifadeyle eşleşip eşleşmediğini ve dosya satırlarını yazdırmaya dayalı olup olmadığını kontrol etmek istiyorum.


1
Beklediğiniz çıktı nedir? Aradığınız desen nedir? Şimdiye kadar ne denedin?
tachomi

@tachomi düzenlenmiş lütfen bir göz atın
Mathew

Yanıtlar:


17

Bunu şu şekilde yapabilirsiniz ed:

ed -s infile <<\IN 2>/dev/null
1s/PATTERN/&/
,p
q
IN

buradaki hile PATTERN, 1sthatta onla değiştirmeye çalışmaktır . edbelirtilen deseni bulamazsa hata verir, bu nedenle ,p(tüm dosyayı yazdır) yalnızca 1s/PATTERN/&/başarılı olursa yürütülür .

Veya sed:

sed -n '1{
/PATTERN/!q
}
p' infile

bu q, ilk satır !eşleşmezse ( ) eşleşmez PATTERN, aksi takdirde ptüm satırları çizer.
Veya Toby Speight'ın işaret ettiği gibi GNU ile sed:

sed '1{/PATTERN/!Q}' infile

Qile aynıdır, qancak desen alanını yazdırmaz.


Yapabilirsin Qyerine qGNU sed için, ya ddaha önce q(taşınabilir) böylece gerek duymaması -nbayrağı ve pkomut: sed '1{/PATTERN/!Q}' infileya sed -e '1{' -e '/PATTERN/!{' -e 'd' -e 'q' -e '}' -e '}' infilesırasıyla.
Toby Speight

dBeni her zaman yakalayan komut döngüsünü yeniden başlatır ! : - |
Toby Speight

GNU sedile ilk sedkomut sed: -e expression #1, char 10: extra characters after command(yüzünden p) şikayet eder , ancak edve son sedöneriler iyi çalışır.
Skippy le Grand Gourou

Not: Bu cevap tarafından sağlanan çözümlerin, diğer cevaplara göre, bir boruya uygulanabilmesinin değeri vardır.
Skippy le Grand Gourou

1
@SkippyleGrandGourou - noktalı virgüllerle komutları ayırmadan tek astar haline getirmeyi denediniz - bunu yapmanın doğru yolu budursed -n '1{/PATTERN/!q};p'
don_crissti

15

POSIX alet sandığı ile:

{ head -n 1 | grep pattern && cat; } <file

1
{double} <tatlı.
mikeserv

@mikeserv: Yeni insanın kafa karıştırmasını önlemek için kullanmayı planlıyorum, ancak Stephane düzenledi.
cuonglm

8
 awk '/pattern/{print FILENAME}; {nextfile}' ./*.txt

olmayan gizli ismini yazdıracak txtolan ilk satır genişletilmiş düzenli ifade ile eşleşen geçerli dizindeki dosyaların patternile o awkinplementations desteğinnextfile .

Dosya adını yazdırmak yerine tüm dosya içeriğini yazdırmak istiyorsanız, şunları yapabilirsiniz:

 awk 'FNR == 1 && ! /pattern/ {nextfile}; {print}' ./*.txt

Bu, yalnızca bir komut çalıştırması açısından etkilidir, ancak awkbir dosyanın içeriğini büyük dosyalarla birlikte dökmek için en verimli komut olmadığından, muhtemelen aşağıdaki gibi bir şey yaparak daha iyi performanslar elde edebilirsiniz:

 awk '/pattern/{printf "%s\0", FILENAME}; {nextfile}' ./*.txt |
   xargs -r0 cat

Yani, yalnızca awkeşleşen (0 ile ayrılmış) dosyaların listesini yazdırmak ve catiçeriklerini dökmek için güvenmek için kullanın.


6

Bir kabuk komut dosyası yazıyorsanız,

for file in ./*; do head -n 1 "$file" | grep -q 'PATTERN' && cat "$file"; done

Veya Perl'de:

perl -Tlne '$f = /PATTERN/ if $. == 1; print if $f; $. = 0 if eof' ./*

@ Stéphane Chazelas: Belki de close ARGVatamaktan daha çok deyimdir $..
cuonglm

@terdon Sizinki kod golf gibi görünüyor, hepsi bir satırda, değişken isimlerin etrafında parantez yok ve temiz bir yapı teşvik etmiyor. Gönderdiğimde dolar işareti kaybettiniz, bu sadece bash öğretmenin yolu değil. Bu faktörlerin de sahip olduğunuz perl arka planından geldiğini varsayıyorum, bu yüzden affedilirsiniz! ;)

@guest merhaba ve siteye hoş geldiniz! Yanıtlarınızı yalnızca asıl soruyu cevaplıyorlarsa gönderilmesi gerektiğinden cevabınızı bir yoruma dönüştürdüm. Bu klasik anlamda bir forum değil ve burada sadece saf soru-cevap istiyoruz. Siteyi daha iyi anlamak için yardım merkezine bir göz atmak veya tura katılmak isteyebilirsiniz. Yani, benim arka plan aslında biyoloji yani evet, benim kod temiz olmaktan uzak olduğunu söyledi :) Ancak, köşeli ayraçlar burada nasıl yardımcı olacağını görmüyorum, tırnak zaten değişkeni korumak. Köşeli parantezlerin koruyacağı şey ne kırabilir?
terdon

@ guest ah, üzgünüm, yorum yapamayacağını unuttum. Sohbette gelip açıklamaktan çekinmeyin , eminim bir şeyler öğrenebilirim.
terdon

5

Oldschool, cümlenizi standart komutlara çevirin:

for file in *; do
    if head -n 1 "${file}" | grep -q 'PATTERN'; then
        cat "${file}"
    fi
done

Bash öğrenmek için bu iyi bir başlangıçtır. Sadece hızlı bir çözüme ihtiyacınız varsa sed-, awk- veya perl-cevaplarını deneyin. Her ikisi de güzel, ama onlar öğrenmek için ihtiyacınız olan (ve muhtemelen istediğiniz) kendi dilleridir.

Oldukça basit bir örnek, bu yüzden daha fazla bilgi edinmek istiyorsanız, aynı şeyi ruby, php, js (örneğin nodejs'de) veya dosya erişimine izin veren başka bir dilde de deneyebilirsiniz. C / C ++ veya Java bile küçük bir görevle kolayca yönetilebilir.


1
Bu temelde benimkinin aynısıdır, if/elsebunun yerine kullandığınız dışında [ ] &&.
terdon
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.