tr -c \\n 1 <testfile | #first transform every [^\n] char to a 1
grep -nF '' | #next get line numbers
paste -d: - testfile | #then paste it together with itself
sort -t: -nk2,2 #then sort on second field
... ve kazanan ... satır 2, öyle görünüyor.
2:1111:4for
4:11111:five!
1:1111111:seven/7
3:11111111:8 eight?
Ancak bununla ilgili sorun, çalışabilmesi için her hattın iki katından daha uzun olması gerekir - yani LINE_MAX etkin bir şekilde yarıya iner. Nedeni kullanıyor olması - ne, bir baz 1? - hattın uzunluğunu temsil etmek. Benzer ve belki de daha düzenli bir yaklaşım, bu bilgiyi akışta sıkıştırmak olabilir. Bu satırlar boyunca meydana gelen ilk fikir, benim yapmam gerekenlerdi unexpand
:
tr -c \\n \ <testfile | #transform all [^\n] to <space>
unexpand -t10 | #squeeze every series of 10 to one tab
grep -nF '' | #and get the line numbers
sed 's/:/!d;=;:/;h;:big #sed compares sequential lines
$P;$!N; /\(:[^ ]*\)\( *\)\n.*\1.*\2/!D #newest line is shorter or...
g;/:./!q;b big' | #not; quit input entirely for blank line
sed -f - -e q testfile #print only first occurrence of shortest line
Bu yazdırır ...
2
4for
Bir tane daha, sadece sed
:
sed -n '/^\n/D;s/\(.\)\(\n.*\)*/\1/g
$p;h; s// /g;G;x;n;//!g;H;s// /g
G; s/^\( *\)\(\n \1 *\)\{0,1\}\n//
D' <infile >outfile
Sözdizimi standartlara uygundur - ancak bu eskilerin hiçbirinin garantisi değildir. sed
kullanımına .\(reference-group\)\{counts\}
doğru şekilde değildir - çoğu yok.
Temelde aynı regexp'i tekrar tekrar girişe uygular - bu onları derleme zamanı geldiğinde çok faydalı olabilir. Bu model:
\(.\)\(\n.*\)*
Farklı şekillerde farklı dizelerle eşleşir. Örneğin:
string1\nstring2\nstring3
... s
içinde \1
ve ''
içinde boş bir dize ile eşleşir \2
.
1\nstring2\nstring3
... 1
içinde \1
ve \nstring2\nstring3
içinde ile eşleşir\2
\nstring2\nstring3
... \n
içinde \1
ve ''
içinde boş bir dize ile eşleşir \2
. \n
Desen uzayının başında bir sınır çizgisi oluşma olasılığı varsa - ve /^\n/D
, //!g
bunu önlemek için komutlar kullanılırsa bu sorunlu olurdu . Kullandım [^\n]
ama bu küçük senaryo için diğer ihtiyaçlar taşınabilirliği bir endişe haline getirdi ve çoğu zaman yanlış yorumlandığı birçok yoldan memnun değildim. Artı, .
daha hızlı.
\nstring2
string1
... maç \n
ve s
tekrar \1
ve elde hem ''
de boş dize \2
. Boş çizgiler hiç uyuşmuyor.
Desen, g
lobally uygulandığında , iki önyargı - hem en soldaki standart önyargı hem de daha küçük olan sağ \n
kenardaki ön kenar önyargısı - bir atlamayı etkilemek için karşı dengededir. Birkaç örnek:
s/\(.\)\(\n.*\)*/\1:\2/g
s/\(.\)\(\n.*\)*/\2\1:/g
s/\(.\)\(\n.*\)*/\1: /g
s/\(.\)\(\n.*\)*/ :\2/g
... tümü aşağıdaki sıraya uygulanırsa (arka arkaya değil) ...
string1\nstring2
... dönüştürecek ...
s:t:r:i:n:g:1:\nstring2
s:t:r:i:n:g:\nstring21:
s:t:r:i:n:g:1:
: : : : : : :\nstring2
Temel olarak regexp'i uygulayacağım herhangi bir desen-uzayda her zaman sadece ilk satırı işlemek için kullanırım. Bu, hem tutulan en kısa eşleşme çizgisinin iki farklı versiyonunu hem de test döngülerine başvurmadan en yeni çizgiyi atmamı sağlıyor - uygulanan her ikame tüm desen alanını bir kerede ele alıyor.
Değişken dizge / dizge karşılaştırmaları için farklı sürümler gereklidir - bu nedenle tüm karakterlerin eşit olmasını garantileyen her satırın bir sürümü olmalıdır. Ancak, eğer biri ya da diğeri aslında girişte en kısa zamanda ortaya çıkan en kısa çizgi olmalıysa, çıktı için yazdırılan çizgi muhtemelen çizginin orijinali olmalıdır - karşılaştırma için sterilize ettiğim / homojenize ettiğim değil. Ve böylece her birinin iki versiyonuna ihtiyacım var.
Başka bir zorunluluğun aynı işlemi yapmak için çok fazla tampon geçişi olması talihsiz bir durumdur - ama en azından hiçbirinde tampon hiçbir zaman güncel kalmak için gereken dört çizgiden daha fazlasını geçemez - ve bu yüzden belki de korkunç değildir.
Her neyse, her döngü için olan ilk şey hatırlanan hatta bir dönüşümdür - çünkü gerçekte kaydedilen tek kopya değişmez orijinaldir - içine ...
^ \nremembered line$
... ve sonra n
ext giriş satırı eski tamponların üzerine yazar. En az bir karakter içermiyorsa, etkin bir şekilde göz ardı edilir. Sadece çok daha kolay olurduq
ortaya çıkan ilk boş satırda , ama, test verilerimde bunlardan çok daha fazlası vardı ve birden çok paragrafla ilgilenmek istedim.
Ve eğer karakter içeriyorsa, edebi versiyonu hatırlanan çizgiye eklenir ve aralıklı karşılaştırma versiyonu kalıp boşluğunun başında bulunur, şöyle:
^ \n \nremembered line\nnew$
Son olarak, bu model alanına bir ikame uygulanır:
s/^\( *\)\(\n \1 *\)\{0,1\}\n//
Bu yüzden eğer yeni satır, hatırlanan satırı, en az bir karakterin yedeklenmesi gereken boşluğu içerecek şekilde sığdırabilirse, ilk iki satır yerine, sadece ilk satır konulur.
D
Sonuçtan bağımsız olarak, desen uzayındaki ilk satır, yeniden başlamadan önce her zaman döngü sonunda ortaya çıkar. Bunun anlamı eğer yeni satır son diziden daha kısaysa ...
new
... her zaman yalnızca ilk satırdaki satırdan sıyrılacak olan döngüdeki ilk yer değiştirmeye geri gönderilir - ve böylece bütün kalır. Ama o zaman dize değilse ...
remembered line\nnew
... bunun yerine bir sonraki döneme başlayacak ve ilk yerleşme ondan sıyrılacak ...
\nnew
...her zaman.
En son satırda, hatırlanan satır standart çıktıya yazdırılır ve bu nedenle verilen örnek veriler için yazdırır:
4for
Ancak, cidden, kullanın tr
.