Yeni satır karakterini yalnızca her N satırdan kaldır


16

Metin işleniyor, her iki satırda yeni satır karakterini kaldırmam gerekiyor.

Örnek yazı:

this is line one
and this is line two
the third and the
fourth must be pasted too

Istenilen çıktı:

this is line one and this is line two
the third and the fourth must be pasted too

Bir whiledöngü denedim , ancak bir while döngüsü kötü bir uygulamadır. Bunu trveya başka bir komutu kullanarak yapmak mümkün mü ?


4
Başlık "her N satırı" der, ancak soru ve örnekte "her 2 satır" dır. Cevapların çoğu sadece N = 2 için geçerlidir. Tüm N için işe yarayan bir şey mi arıyorsunuz?
JigglyNaga

Anahtar bu. Herkes 2 satır için cevap verdi ama N = 3 veya N = 4 kullanmam gerekecek
jomaweb

Yanıtlar:


24

paste(ayrıca standart bir POSIX gibi basit bir yardımcı program tr) bunun için bir araçtır.

Bu yeni satır karakterlerinin , örneğin örneğinizdeki gibi kaldırılmak yerine bir boşlukla değiştirilmesini istediğiniz varsayarsak :

paste -d ' ' - - < file

Veya:

paste -sd ' \n' file

Değiştir ' 'ile '\0'bunları kaldırılmasını istiyorum gerçekten yaparsan.

3 üzerinden 2'yi değiştirmek için:

paste -sd '  \n' file

3'ten 1, ikinciden başlayarak:

paste -sd '\n \n' file

Ve bunun gibi.

Başka bir iyi şey, pastesonlandırılmamış bir satır bırakmayacak olmasıdır. Örneğin, bir dosyadaki her yeni satırı ( tr -d '\n' < fileveya ile olduğu gibi tr '\n' ' ' < file) kaldırırsanız, satırların yeni satır karakteriyle sonlandırılması gerektiği için hiçbir satır olmazsınız. Bu nedenle , geçerli metne sahip olmak için gerekli olan son satırsonu karakterini ekleyecek olan paste(içinde paste -sd '\0' fileveya gibi paste -sd ' ' file) yerine kullanmak genellikle daha iyidir .


11

Modern GNU sed ile

sed -rz 's/\n([^\n]*\n)/ \1/g' sample.text

Ve garip

awk '{getline line2;print $0, line2}' sample.text

3
Bu sedyaklaşım (NUL bayt içermiyorsa) tüm dosyayı bellekte inceltmek ve bazı pahalı normal ifade yerine koyma yapmak anlamına gelir. Standart sed 'N;s/\n/ /'yaklaşımdan daha fazla fayda göremiyorum .
Stéphane Chazelas

6

Bunun sediçin aşağıda gösterildiği gibi kullanın :

SHW@SHW:/tmp $ cat a
this is line one
and this is line two
the third and the
fourth must be pasted too

SHW@SHW:/tmp $ sed 'N;s/\n/ /' a -i

SHW@SHW:/tmp $ cat a
this is line one and this is line two
the third and the fourth must be pasted too

4

Başka bir yol da kullanmaktır xargs:

$ < txt xargs -d '\n' -n 2 echo
this is line one and this is line two
the third and the fourth must be pasted too

nerede

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

Bu çözüm oldukça aşırı olmasına rağmen, echo her çizgi için işlem yürütülür ... Bu nedenle, oyuncak örneklerinin yanı sıra, awk / sed veya benzeri bir çözelti tercih edilmelidir.


1
Uygulamanıza bağlı olarak, echoters eğik çizgi karakterleriyle veya -( GNU gibi --helpveya -neneile başlayan) bazı satırlarla ilgili sorunlarınız da olacaktır echo. Ayrıca bunun -dbir GNU uzantısı olduğuna dikkat edin .
Stéphane Chazelas

echo< txt xargs -d '\n' -n 2 printf -- '%s %s\n'
İle

4

Bu aslında vim'de son derece basit. Her satıra katılmak için şu Jkomutu kullanın:%norm her satıra aynı anda uygulamak komutu kullanın. Örneğin

:%norm J<CR>

(Vim'e aşina değilseniz, <CR>girmek anlamına gelir)

Bu, rastgele sayıda hatta katılmak için bile çalışır. Örneğin, her on satıra katılmak

:%norm 9J<CR>

Vim'den rahatsızsanız ve bunu etkileşimli bir metin düzenleyicisi yerine bir komut satırı aracı olarak kullanmayı tercih ederseniz, şunları yapabilirsiniz:

vim myfile -c '%norm J' -c 'wq'

Downvoter bu cevabı geliştirmek için neler yapabileceğimi açıklar mı?
DJMcMayhem

3
$ awk '{printf "%s%s",$0,(NR%2?" ":"\n")}' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

Bu, her satırı yazdırır $0, ardından satır numarasına bağlı olarak bir boşluk veya bir yeni satır NRtek veya çift olur.

İfade NR%2?" ":"\n" üçlü bir ifadedir. NR%2Satır numarası tekse ifade doğru (sıfır olmayan) olarak değerlendirilir. Bu durumda, üçlü ifade bir boşluk döndürür. False (sıfır) olarak değerlendirilirse, yeni satır döndürülür.

Alternatif

Costas tarafından yorumlarda önerildiği gibi:

$ awk '{ORS=(NR%2?" ":RS)}1' sample.txt
this is line one and this is line two
the third and the fourth must be pasted too

Burada üçlü ifadesi NR%2?" ":RSboşluk veya giriş kayıt ayırıcısını döndürmek için kullanılır ( RS, default = newline). Bu değer çıkış kayıt ayırıcısına atanır ORS. 1Komutun sonunda baskıya-kayıt için awk şifreli kısaltmasıdır.


Yine de 3 karakter kaydedebilirsiniz: ()parantez ve sonraki boşluk printf;)
maxschlepzig

1
Üçlü? Ah! 'NR%2{printf("%s ",$0);next}1'
Costas

İle maxschlepzig cevabı : ve üçlü açıklamada'{ORS=(NR%2?" ":RS)}1'
Kostas

@Costas bunu beğendim. Yanıt ORSçözüm ile güncellendi .
John1024

2

Genel çözüm, 5gereken satır sayısı ile değiştirin

$ # eof to ensure last line has newline ending
$ seq 16 | perl -pe 's/\n/ / if ++$i%5 && !eof'
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

$ # or just use pr
$ seq 16 | pr -5ats' '
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16

1

Bunun için kullanabilirsiniz awk:

$ awk '{c="\n"} NR%2 {c=" "} { printf("%s%s", $0, c) } ' txt

Ürettiği:

this is line one and this is line two
the third and the fourth must be pasted too

nerede:

$ cat txt
this is line one
and this is line two
the third and the
fourth must be pasted too

awkHerbir çizgi, özel değişken için yürütülür $0referanslar mevcut hat, NRmevcut satır numarası (1 den başlayarak gibi). İkinci eylem, NR%2modulo işlemi olan ifade ile korunur . Bu nedenle, c=" "yalnızca NR%2doğruysa, yani tek satır numaraları için yürütülür .

awkSözdizimi gibi C, ancak bazı unsurlar bazı bağlamlarda isteğe bağlıdır - örneğin noktalı virgül.


Sizin cdeğişkendir ORS:'NR%2{ORS=" "}1;{ORS=RS}'
Kostas

0

Kullanma ed:

$ cat text
this is line one
and this is line two
the third and the
fourth must be pasted too
this is line one
and this is line two
the third and the
fourth must be pasted too

$ ed text <<'END_ED'
g/./s/$/ /\
j
w text.new
END_ED
164
164

$ cat text.new
this is line one and this is line two
the third and the fourth must be pasted too
this is line one and this is line two
the third and the fourth must be pasted too

edHer hat için (will düzenleme komutları gverilen düzenli ifade ile eşleşen her satırı komutları düzenlerken bir dizi geçerlidir), sonuna bir boşluk karakteri ekleyin ve sonraki satırda ile katılmak. Sonra ortaya çıkan metni adlı bir dosyaya yazar text.new.


0

Ruby ile.

Her nsatır bloğunun birleştirileceğini varsayıyorum . n = 3Giriş dosyasının olduğunu 'infile've sonuçların dosyaya yazılacağını varsayalım 'outfile'.

Bir dosya oluşturma

Ruby -e "File.write 'infile', <<_
> Line 1
> Line 2
> Line 3
> Line 4
> Line 5
> Line 6
> Line 7
> _"

Dosyanın içeriğini onaylayın

ruby -e "p File.read 'infile'"
  # "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\n"

Yeni satırları kaldırın ve dosyaya yazın

ruby -e "File.write 'outfile', File.readlines('infile').
  each_with_index { |line,i| line.chomp! unless (i+1)%3==0 }"

İçeriği onayla

ruby -e "puts File.read 'outfile'"
  # ["Line 1", "Line 2", "Line 3\n", "Line 4", "Line 5", "Line 6\n", "Line 7"]

1
İyi bir. Teorik olarak, rubyU&L konusunda konu dışıdır. Ancak, komut satırından onu kullandığınız için ruby -e, bu konu üzerinde yeterli hale getirir.
grochmal
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.