Son yorumlanan satırdan 'foo' satırına tüm satırları yorumlayın


12

Bir metin dosyası düşünün users.txt:

#alice
#bob
charlie
dotan
eric

Ben (özel) son yorum satırından (dahil) kadar her şeyi yorumlamak gerekiyor dotan. Sonuç budur:

#alice
#bob
#charlie
#dotan
eric

sedBunu yapmak için hoş bir oneliner var mı ? sedGerçekten değil, herhangi bir araçtan memnun olacağım .

Şu anda son yorum satır satır numarasını alıyorum gibi:

$ cat -n users.txt | grep '#' | tail -n1
  2 #bob

Sonra bir tane ekleyin ve ile yorum sed:

$ sed -i'' '3,/dotan/ s/^/#/' users.txt

Zeki olabileceğimi ve bunları bazılarıyla bcçirkin tek bir astar içine koyabileceğimi biliyorum . Elbette daha temiz bir yol olmalı mı?

Yanıtlar:


5

Peki ya

perl -pe '$n=1 if s/^dotan/#$&/; s/^[^#]/#$&/ unless $n==1;' file

veya awk ile aynı fikir:

awk '(/^dotan/){a=1; sub(/^/,"#",$1)} (a!=1 && $1!~/^#/){sub(/^/,"#",$1);}1; ' file

7

Mevcut yorum satırları tek bir bitişik blok oluşturuyorsa, bunun yerine ilk yorum yapılan satırdan eşleşebilir ve yalnızca henüz yorumlanmamış bitiş kalıbınıza kadar olan ve bu satır dahil olan satırları yorumlayabilirsiniz

sed '/^#/,/dotan/ s/^[^#]/#&/' file

Mevcut yorumlar bitişik değilse, sed aralığı eşleşmesinin açgözlü doğası nedeniyle bence böyle bir şey yapmanız gerekeceğini düşünüyorum

tac file | sed '/dotan/,/^#/ s/^[^#]/#&/' | tac

yani son modelden 'ilk' yoruma kadar yukarı doğru eşleştirin - tabii ki yerinde bir çözüm istiyorsanız bu çok uygun değildir.


4

Her iki durumu da (tek bir bitişik blokta yorumlanmış satırlar veya yorumlanmamış satırlar arasında serpiştirilmiş) tek bir sedçağrı ile işleyebilirsiniz :

sed '1,/PATTERN/{/^#/{x;1d;b};//!{H;/PATTERN/!{1h;d};//{x;s/\n/&#/g}}}' infile

Bu yalnızca 1,/PATTERN/aralıktaki çizgileri işler . Bu e xdeğişiklikler ağırlık alana sahiptir. bir satır her yorumlandığında desen alanı (bu nedenle tutma arabelleğinde asla birden fazla yorumlu satır bulunmaz) ve Heski alana yorum yapılmamış her satırı (1. satırdayken 1dve sırasıyla ilk satırın 1hkaldırılması gerekir ) ekler tutma tamponundaki boş satır).
PATTERN ile eşleşen satıra ulaştığında, aynı zamanda Heski arabelleğe ekler , e xarabellekleri değiştirir ve daha sonra \ndesen alanındaki her ewline karakterini bir \newline ve a ile değiştirir #(yani, desen alanındaki tüm satırlar şimdi #, ilk satırı, bekleme alanındaki ilk satır olarak dahil etmek her zaman yorumlanmış bir satırdır).
Bir örnekle infile:

alice
#bob
bill
#charlie
ding
dong
dotan
jimmy
#garry

çalışan:

sed '1,/dotan/{                   # if line is in this range    -start c1
/^#/{                             # if line is commented        -start c2
x                                 # exchage hold space w. pattern space
1d                                # if 1st line, delete pattern space
b                                 # branch to end of script
}                                 #                             -end c2
//!{                              # if line is not commented    -start c3
H                                 # append to hold space
/dotan/!{                         # if line doesn't match dotan -start c4
1h                                # if 1st line, overwrite hold space
d                                 # delete pattern space
}                                 #                             -end c4
//{                               # if line matches dotan       -start c5
x                                 # exchage hold space w. pattern space
s/\n/&#/g                         # add # after each newline character
}                                 #                             -end c5
}                                 #                             -end c3
}' infile                         #                             -end c1

çıktılar:

alice
#bob
bill
#charlie
#ding
#dong
#dotan
jimmy
#garry

yalnızca satırdan (ve hariç) satırlara #charlie(ve dahil) yorum yapar dotanve diğer satırlara dokunulmaz.
Elbette, bu, satır eşleşmesinden önce her zaman en az bir yorumlu satır olduğunu varsayar PATTERN. Durum böyle değilse, değiştirmeden önce ek bir kontrol ekleyebilirsiniz:/^#/{s/\n/&#/g}


Teşekkür ederim, bu cevaptan öğrenecek çok şeyim olacak!
dotancohen

Bekle, berbat olmalıyım. Bu, yorum yapılan son satırlarla ilgili değil mi? Hayır, anladım, öyle. Son seri + dotan. Oldukça akıllı.
mikeserv

1
Her zaman en iyi soruları bulabilirsiniz. Lanetlenmiş dotan beni bir süreliğine fırlattı - belki de hala test etmedim. teşekkürler, don.
mikeserv

2

İşte bir başkası sed:

sed  -e:n -e'/\n#.*\ndotan/!{$!{N;/^#/bn'      \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g' \
-et  -e\} -eP\;D <in >out

İstediğiniz gibi yapar. Sadece bir yığın üzerinde çalışır - gerektiğinde ve yorumlanmış satırların oluşumları arasında gerektiği kadar bina ve eski arabelleği yeni yorumlanmış satır lehine bir tane bulduğunda girdi olarak daha da boşaltır. Resim...

resim açıklamasını buraya girin

Üzgünüm, bunu neden yaptığımı bilmiyorum. Ama aklıma geldi.

Her neyse, sedarabelleklerini herhangi bir dizideki son yorumlanan her satır arasına yayar, hiçbir zaman arabellekte son yorumlanan olayı doğru bir şekilde izlemek için gerekenden daha fazla tutmaz ve bunu yaparken herhangi bir zamanda son satırla karşılaşırsa, son global yürütme ifadesi ve şube t, yazdırılacak tüm arabelleği doldurur , yoksa Pen kısa sürede arabelleğinden serbest bıraktığı tüm satırları dizginler .

Akordeonları akla getiren şey bu ...

printf %s\\n   \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric \
               \#alice \#bob charlie dotan eric |
sed  -e:n -e'l;/\n#.*\ndotan/!{$!{N;/^#/bn'     \
-eb  -e\} -e'/^#/s/\(\n\)\(dotan.*\)*/\1#\2/g'  \
-et  -e\} -eP\;D

#alice
#alice\n#bob$
#alice\n#bob\ncharlie$
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob\ncharlie\ndotan\neric\n#alice$
#bob\ncharlie\ndotan\neric\n#alice\n#bob$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie$
#bob\ncharlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
#bob
charlie\ndotan\neric\n#alice\n#bob\ncharlie\ndotan$
charlie
dotan\neric\n#alice\n#bob\ncharlie\ndotan$
dotan
eric\n#alice\n#bob\ncharlie\ndotan$
eric
#alice\n#bob\ncharlie\ndotan$
#alice
#bob\ncharlie\ndotan$
#bob\ncharlie\ndotan\neric$
#bob
#charlie
#dotan
eric

Bu komut ile yukarıdaki komut arasında tek bir fark vardır ve bu lüstteki ook komutudur. Biz ne zaman lbiz Ook sedçalıştığını olarak 'nın desen alanı biz perde arkasında neler olup bittiğine dair daha iyi bir fikir ve çabalarını yönlendirmek için nasıl daha iyi anlamak alabilirsiniz.

Bu durumda, sedgirişte ikinci bir oluşum bulunana kadar yığın girişini izleyebiliriz \n#.*\ndotanve bir kerede bir önceki satırı yazdırmaya başlar. Çok havalı. Bu konuda çok şey öğrendim.


Çok güzel teşekkür ederim! Açıklamaları olan son paragraf müthiş, bu yazıdan da öğrenmeye biraz zaman harcayacağım. Güzel yığın!
dotancohen

1
@dotancohen - bu gerçekten iyi bir soruydu. Yığını görmek için düzenlemeye bakın .
mikeserv

2
Düzenleme geçmişinde girişi fark ettim Handle many dotans. Eminim bu karımın en kötü kabusu.
dotancohen

1
@dotancohen - evet, bu zor biriydi. Gibi #\ndotan\ndotanşeyler bu şeyler için zor. Bunu iyi bir soru dediğimde kastediyorum. Ben düşünüyorum ben hemen mükemmel aldım, ama bir sorun olabilir yorumunuz blokları 1000 çizgilerle ayrılır eğer girmek - yani olacaktır yavaşla. Örneğin, 150 satıra yayılırsa arabelleği çıkarmak için s/\n/&/150;tilk /\n#şeyden önce olduğu gibi bir şey yapıştırabilirsiniz . Ve yine, belki de o bekliyordu olan şey baştan beri !
mikeserv
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.