Dosyanın sonuna kadar bir eşleşme sonrasında tüm satırlar nasıl yazdırılır?


48

Giriş dosyası1:

dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

Eşleşmeyi kalıbın içinden other file( dog 123 4335file2'deki gibi ) veriyorum .

Çizginin deseni ile eşleşiyorum dog 123 4335ve tüm çizgileri eşleşme çizgisi olmadan yazdırdıktan sonra çıktım :

cat 13123 23424
deer 2131 213132
bear 2313 21313

Eğer sadece adres adresi olmayanlar sadece kalıbı kullanırsa, örneğin 1s satırları nasıl eşleştirip yazdıralım?


Diğer dosya aranacak tek satırlık bir desen içerebilir mi, yoksa her satır için bir tane mi ve aranan dosyada ilk bulunan hangi satırda aramaya başlayabilir?
Ciro Santilli 事件 52

Yanıtlar:


27

Tüm çizgiyi modelinizle eşleştirmek istediğinizi varsayarsak, GNU ile sed, bu işe yarar:

sed -n '/^dog 123 4335$/ { :a; n; p; ba; }' infile

Standart eşdeğer:

sed -ne '/^dog 123 4335$/{:a' -e 'n;p;ba' -e '}' infile

Aşağıdaki girişle ( infile):

cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

Çıktı:

cat 13123 23424 
deer 2131 213132
bear 2313 21313

Açıklama:

  • /^dog 123 4335$/ istenen deseni arar.
  • :a; n; p; ba;input ( n) ' dan yeni bir satır alan , onu ( p) basan ve a etiketine geri dallayan bir döngüdür :a; ...; ba;.

Güncelleme

İhtiyaçlarınıza daha yakın bir cevap, yani file2'deki pattern, file1'den grepping:

tail -n +$(( 1 + $(grep -m1 -n -f file2 file1 | cut -d: -f1) )) file1

Gömülü grep ve kesim, file2'den bir desen içeren ilk satırı bulur, bu satır numarası artı biri kuyruğa geçirilir, artı biri desen ile çizgiyi atlamak için orada bulunur.

İlk karşılaşma yerine son karşılaşmadan başlamak istiyorsanız, şu şekilde olur:

tail -n +$(( 1 + $(grep -n -f file2 file1 | tail -n1 | cut -d: -f1) )) file1

Tüm kuyruk sürümlerinin artı gösterimi desteklemediğini unutmayın.


Bu, sed'de, çok uzaklara götürmek gibi hissetmeyen, gördüğüm n ve p komutlarının ilk örneğidir. Görünüşe göre (benim kısa testlerimden) sed -n '/^dog 123 4335$/ { :a; p; n; ba; }' infile(p ve n anahtarlı) başarıyla eşleşen çizgiyi de içeriyor.
Josiah Yoder,

26

Oldukça kısa bir dosyanız varsa, greptek başına işe yarayabilir:

grep -A5000 -m1 -e 'dog 123 4335' animals.txt

5000, grepilk eşleşmeyi bulduğu ve bir sonraki 5000 satırla birlikte çıktığı için (dosyanın bu kadarına sahip olması gerekmez) olduğu gibi , "makul ölçüde kısa" olan benim tahminim . Kibritin kendisini istemiyorsanız, kesmeniz gerekir, örn.

grep -A5000 -m1 -e 'dog 123 4335' animals.txt | tail -n+2


Birinciyi istemiyorsanız, ancak son sınırlayıcıyı sınırlayıcı olarak kullanabilirsiniz:

tac animals.txt | sed -e '/dog 123 4335/q' | tac

Bu satır animals.txt, satır sırasını tersten okur ve satırın başına ve satırına dahil olan çıktıları alır dog 123 4335ve ardından doğru sırayı geri almak için tersine döner.

Yine, sonuçtaki maça ihtiyacınız yoksa, kuyruk ekleyin. (Çıkmadan önce arabelleğini atmak için sed ifadesini de karmaşıklaştırabilirsiniz.)


Testime göre GNU grep 3.0, bağlamdan sonra (belirtilen değer ne olursa olsun) 132 satırdan fazla çıktı vermiyor.
ruvim

22

Pratikte muhtemelen kullanmayı tercih ediyorum Aet3miirah yanıtını zaman ve çoğu alexey cevabı hatları (ayrıca, aynı zamanda çalışır gezinmek isteyen zaman harika less). OTOH, gerçekten başka bir yaklaşımı sevdim (tersine çevrilmiş Gilles'un cevabına benziyor :

sed -n '/dog 123 4335/,$p'

-nBayrak ile çağrıldığında , sedvarsayılan olarak işlediği satırları yazdırmaz. Ardından, satır eşleştirmeden /dog 123 4335/dosyanın sonuna kadar (tarafından temsil edilen $) bir komut uygulanmasını söyleyen 2 adresli bir form kullanırız . Söz konusu komut p, geçerli satırı basan komuttur . Yani bu, "bir satırdaki eşleştirmeden /dog 123 4335/sonuna kadar tüm satırları yazdır" anlamına gelir .


3
Bu, istenmediği halde dogçizgiyi basar .
Stéphane Chazelas 10:15

1
Bu, en iyi cevaba benziyor (ve kendi davam için çalışıyor) ancak eşleşen çizgiyi atlamak için de uyarlanması gerekiyor.
Pavel Šimerda

1
sed -n '/ köpek 123 4335 /, $ p' | sed '1d' köpek çizgisini kaldıracak
Kemin Zhou

1
sed -n '/dog 123 4335/,$p' | tail -n +2Maçı da kaldıracak
gilad mayani

15
sed -e '1,/dog 123 4335/d' file1

Deseni bir dosyadan okumanız gerekiyorsa, onu sed komutunun yerine koyun. Dosya sed desen içeriyorsa:

sed -e "1,/$(cat file2)/d" file1

Dosya aranacak değişmez bir dize içeriyorsa, tüm özel karakterleri alıntılayın. Dosyanın tek bir satır içerdiğini tahmin ediyorum.

sed -e "1,/$(sed 's/[][\\\/^$.*]/\\&/g' file2)/d" file1

Eşleşmenin sadece bir alt dize değil, tüm çizgi olmasını istiyorsanız, deseni yerleştirin ^…$.

sed -e "1,/^$(sed 's/[][\\\/^$.*]/\\&/g' file2)\$/d" file1

6
Desen ilk satırdaysa bu işe yaramaz. GNU sedbunun 0,/dog.../diçin var.
Stéphane Chazelas 10:15

14

$ more +/"dog 123 4335" file1


4
Aynı zamanda çalışır less.
brandizzi

3
Terminalde akıllıca, ancak başka bir şeye bağlarsanız, aslında işe yaramaz tac.
jcomeau_ictx

bu şekilde kullanıyorum, $ more + / "kelimelerimi eşleştir" file1 >> file2
AMB

1
Belki POSIX 7'de +değiştirildi -p: pubs.opengroup.org/onlinepubs/9699919799/utilities/more.html ancak util-linux 2.20.1'de henüz uygulanmadı. Ve bu da basar skipping..ve bazı ekstra yeni satırlar (beklediğimden daha iyi olabilir).
Ciro Santilli 新疆 41 中心 法轮功 六四 事件

belki o zamandan beri işler değişti? yorumum 3 oy aldı bu yüzden o zamanlar ilgili olabilirdi ...
jcomeau_ictx

11

İle awk:

awk 'BEGIN {getline pattern < "other file"}
   NR == 1, $0 ~ pattern {next}; {print}' < "input file"

5

Awk kullanmanın bir yolu:

awk 'NR==FNR{a[$0];next}f;($0 in a){f=1}'  file2 file1

file2 arama kalıplarınızı içerir. İlk önce, file2 dosyasının tüm içeriği "a" dizisinde saklanır. File1 işlendiğinde, her satır diziye karşı kontrol edilir ve sadece mevcut değilse yazdırılır.


Bence OP, deseni izleyen her satırın çıktısını almak istiyor.
Thor,

@Thor: Gösterdiğin için teşekkürler, şimdi güncelledi ...
Guru

Güzel bitti :).
Thor'un

5

Girdi, aranabilir normal bir dosyaysa :

GNU ile grep:

{ grep  -xFm1 'dog 123 4335' >&2
  cat; } <infile 2>/dev/null >outfile

İle sed:

{ sed -n '/^dog 123 4335$/q'
  cat; } <infile >outfile

grepW / the -mseçenek olarak adlandırılan bir GNU maçta girişi bırakacaktır - ve son aranan noktayı bulduktan hemen sonra (aranabilir) girişini bırakacaktır . Böylece, grepw / çağıran bir şablonda -m1bir modelin ilk oluşumunu bulur ve catmodelin ilk eşleşmesinden sonra her şeyi bir dosyada stdout'a yazmak için giriş ofsetini doğru yerde bırakır .

Bir GNU'suz bile grepPOSIX ile uyumlu olan aynı şeyi yapabilirsiniz sed- uygun olduğunda sed q, giriş ofsetini olduğu yerde bırakması gerektiği belirtilir. GNU sedbu şekilde standartlara uygun değildir ve bu nedenle, sedsiz -uanahtarına basmadığınız sürece yukarıdaki muhtemelen GNU ile çalışmaz .


sedburada gösterilen akış paylaşımının özel olarak yapılmamasına dikkat edin (evet, evet, gösterilen özel sedbiçimli ve işbirliğine dayalı iş akışının özel bir örneğini bu şekilde yapabilecek bir örnek olarak gösterebilir). özellikle, tüm standart uygulamalar bir sonraki okuyucunun hiçbir işleminde başarısız olmadan giriş akışlarının imleç pozisyonlarını işbirliği ve paylaşma amaçlıdır. grep -qbunu yapmalı; grepgiriş içindeki herhangi bir eşleşme bulunur bulunmaz sessizce geri dönülmeli ve girişin geri kalanı standart olarak tüketilmemelidir.
mikeserv

4

Konuyla ilgili soruya cevabım, ikinci bir dosyaya desen kaydetmeden. İşte benim test dosyası:

$ cat animals.txt 
cat 13123 23424 
deer 2131 213132
bear 2313 21313
dog 123 4335
cat 13123 23424 
deer 2131 213132
bear 2313 21313

GNU sed:

 $ sed '0,/^dog 123 4335$/d' animals.txt 
 cat 13123 23424 
 deer 2131 213132
 bear 2313 21313

Perl:

$ perl -ne 'print unless 1.../^dog 123 4335$/' animals.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

Bir dosyada desenli Perl değişken:

$ cat pattern.txt 
dog 123 4335
$ perl -ne 'BEGIN{chomp($p=(<STDIN>)[0])};print unless 1../$p/;' animals.txt < pattern.txt
cat 13123 23424 
deer 2131 213132
bear 2313 21313

2

Wth ed:

ed -s file1 <<< '/dog 123 4335/+1,$p'

Bu p, here-string içindeki ed'ye bir rint komutu gönderir ; print komutu ( ) eşleşmesinden sonra ( +1) dog 123 4335dosyanın sonuna kadar ( ) eşleşecek şekilde sınırlıdır $.


1

Geçici bir dosya oluşturulmasına aldırmazsanız ve elinizde varsa csplit, bu işe yarar:

sh -c 'csplit -sf"$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

Not file1giriş dosyasıdır ve file2kalıp dosyasıdır (soruda belirtildiği gibi).

Yukarıdaki komutun uzun şekli:

sh -c 'csplit --quiet --prefix="$1_" "$1" "%^$(cat "$2")%+1" && cat "${1}_00"' sh file1 file2

yani

csplit --quiet --prefix="file1_" "file1" "%^$(cat "file2")%+1" && cat "file1_00"

csplitprefixyukarıdaki bayrak olmadan dosyayı oluşturacak xx00(önek olmak xxve sonek olmak 00). Yukarıdaki bayrak ile dosya oluşturur file1_00. quietBayrak olmadan, çıktı dosyasının boyutunu (elde edilen dosyanın boyutu) yazdırır.


0

Awk açıkça reddedilmediğinden, işte 'kedi' nin eşleşme olduğunu farz ediyorum.

awk '$0 ~ /cat/ { vart = NR }{ arr[NR]=$0 } END { for (i = vart; i<=NR ; i++) print arr[i]  }' animals.txt

0

Dosyanın sonuna kadar bir eşleşme sonrasında tüm satırlar nasıl yazdırılır?

Bunu koymak için bir başka yol da "1 satırından ilk satırdaki eşleşmeye kadar tüm satırların nasıl silineceği" dir ve şöyle sedyazılabilir:

sed -e '1,/MATCH PATTERN/d'

1
Tek sorun, model ilk
satırdayken


Sanırım karar vermek için burada bir komiteye ihtiyacımız var.
poige

1
@poige: nah, aynı cevabı daha az kapsamlı olarak veriyorsunuz
Thor

@ don_crissti, peki ya sed -e '0,/MATCH PATTERN/d'sonra?
Velkan
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.