Sed kullanarak bir satırsonu (\ n) nasıl değiştirebilirim?


1371

Komut satırını kullanarak bir satırsonunu (" \n") bir boşlukla (" ") nasıl değiştirebilirim sed?

Başarısız denedim:

sed 's#\n# #g' file
sed 's#^$# #g' file

Nasıl düzeltebilirim?


27
trtek bir karakter için tek bir karakter yerine, sadece iş için doğru araçtır, yukarıdaki örnek newline yerine bir boşluk gösterir .. Yani yukarıdaki örnekte, tr işe yarayabilir .. Ama daha sonra sınırlı olacaktır.
Kızgın 84

9
trçünkü soru soran kişi, her yeni satırı kendi örneğinde gösterildiği gibi bir boşlukla değiştirmek istedi. Yeni satırların değiştirilmesi benzersiz bir şekilde gizlidir, sedancak kolayca yapılabilir tr. Bu yaygın bir soru. Regex değiştirmeler yaparak yapılmazsa trama tarafından seddoğru araç ... Farklı soru için olacağını.
Mike S

3
"tr" aynı zamanda yeni satır tr `d -d '\ n' 'silebilir, ancak dönüşleri daha evrensel bir` `tr -d' \ 012 \ 015 '' olarak silmek de isteyebilirsiniz.
Anthony

2
UYARI: "tr", Linux ve daha eski Solaris makineleri (EG sol5.8) arasındaki karakter aralıklarına göre farklı davranır. EG: `tr -d 'az' 've` tr -d' [az] ''. Bunun için bu farkı olmayan "sed" kullanmanızı tavsiye ederim.
Anthony

2
@MikeS Cevabınız için teşekkürler. tr '\012' ' 'Bir ile takip edin echo. Aksi takdirde, dosyadaki son satır beslemesi de silinir. tr '\012' ' ' < filename; echohile yapar.
Bernie Reiter

Yanıtlar:


1513

Bu çözümü GNU ile kullanın sed:

sed ':a;N;$!ba;s/\n/ /g' file

Bu, tüm dosyayı bir döngü içinde okuyacaktır, ardından yeni satırları bir boşlukla değiştirecektir.

Açıklama:

  1. Yoluyla bir etiket oluşturun :a.
  2. Geçerli ve sonraki satırı ile desen alanına ekleyin N.
  3. Son satırdan önce olursak, oluşturulan etikete dallanır $!ba( $!son satırda bunu yapmamak anlamına gelir, çünkü son satırda bir son satır olmalıdır).
  4. Son olarak, ikame her satırsonu model uzayındaki bir boşlukla değiştirir (dosyanın tamamıdır).

İşte BSD ve OS X'lerle çalışan platformlar arası uyumlu sözdizimi sed( @Benjie yorumuna göre ):

sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' file

Gördüğünüz gibi, sedaksi takdirde bu basit problemi kullanmak sorunludur. Daha basit ve yeterli bir çözüm için bu cevaba bakınız .


45
@Arjan ve Masi: OS X, sedGNU yerine BSD kullanır sed, bu nedenle bu ikisinde bazı (ve bu kadar ince olmayan) bazı farklılıklar olabilir. Hem OS X hem de * nix makinelerde çalışıyorsanız bu sürekli bir acıdır. Genellikle GNU'ları coreutilsve findutilsOS X'e yüklerim ve BSD sürümlerini yoksayarım.
Telemachus

50
:aBir dal etiketi var, bir kayıt yoktur. Bu, b"goto" gibi çalışan komut * için bir hedeftir . Kayıt olarak adlandırmak, depolama yerleri oluşturabileceğiniz anlamına gelir. Sadece iki "kayıt" vardır; bunlardan birine komut dosyanızın kullanmadığı "tutma alanı", diğerine "desen alanı" adı verilir. NKomut Yeni satır ve ve desen boşluğa giriş dosyasının sonraki satırını ekler. [* Birden fazla etiketiniz ve bkomutunuz olabilir. bBir etiket karakteri eklenmemiş bir komutunuz varsa, bir sonraki satırı okumak ve tekrar döngü oluşturmak için komut dosyasının sonuna
dallanır

108
Bu çapraz platformu (yani Mac OS X'te), noktalı virgüllerle ayırmak yerine komutları ayrı ayrı çalıştırarak çalıştırabilirsiniz: sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g'
Benjie

74
Neden kimse bunun ne kadar aptal bir karışıklık olduğunu yorumlamıyor (cevabın kendisi değil, önerilen cevabın çok basit bir soruna en iyi çözüm olduğu program). Sed, genellikle iyi çalışan bir arabaya benziyor, ancak yakındaki belirli bir sokağa gitmek istiyorsanız, tek yol arabayı helikopterle kaldırmaktır.
Ark-kun

12
Haydi millet - işe yaramaz çılgın, anlaşılmaz bir çözüm için 261 upvotes ???? sed, tek bir satırdaki basit geçitler için mükemmel bir araçtır, başka bir şey için sadece awk kullanın. İyi keder ....
Ed Morton

1711

sedhat tabanlı girişte kullanılmak üzere tasarlanmıştır. Gereksinim duyduğunuz her şeyi yapabilir.


Burada daha iyi bir seçenek, trkomutu aşağıdaki gibi kullanmaktır :

tr '\n' ' ' < input_filename

veya yeni satır karakterlerini tamamen kaldırın:

tr -d '\n' < input.txt > output.txt

veya GNU sürümünüz varsa (uzun seçenekleriyle)

tr --delete '\n' < input.txt > output.txt

88
Sed çizgi tabanlıdır, bu nedenle yeni satırları kavraması zordur.
Alexander Gladysh

191
sed bir girdi "akışı" üzerinde çalışır, ancak yeni satırla sınırlandırılmış parçalar halinde bunu kavrar. Unix bir araçtır, yani bir şeyi çok iyi yapar. Tek şey "bir dosya üzerinde çalışmak". Başka bir şey yapmak zor olacak ve buggy olma riski var. Hikayenin ahlakı: doğru aracı seçin. Sorularınızın büyük bir kısmı "Bu aracın, asla yapılmaması gereken bir şeyi nasıl yapmasını sağlayabilirim?" Bu sorular ilginç, ancak gerçek bir sorunu çözme sürecinde ortaya çıkarlarsa, muhtemelen yanlış yapıyorsunuz.
dmckee --- eski moderatör kedi yavrusu

7
@JBBrown tr, boru hatları inşa etmek için göz ardı edilen bir mücevherdir.
dmckee --- eski moderatör yavru kedi

70
tr harika, ancak yeni satırları yalnızca tek karakterlerle değiştirebilirsiniz. Yeni satırları bir dizeyle değiştirmek istiyorsanız farklı bir araç kullanmanız gerekir
Eddy

21
@Eddy - Yeni satırları metinde görünmeyen bir karakterle değiştirmek için kullandım (backtick kullandım), sonra backtick'i kullanmak istediğim dize ile değiştirmek için sed kullandım
rjohnston

494

Hızlı cevap

sed ':a;N;$!ba;s/\n/ /g' file
  1. : a 'a' etiketi oluştur
  2. N desen uzayına sonraki satırı ekler
  3. , $! son satır değilse , ba dalı (git) 'a' etiketi
  4. s yerine , / \ n / regex yeni satır , / / boşluk , / g global eşleşme (olabildiğince çok)

sed, son satıra ulaşana kadar adım 1 ila 3 arasında döngü yapar ve tüm satırlar, sed'in tüm karakterlerin yerine geçeceği desen alanına sığdırır \ n


Alternatifler

Tüm alternatiflerin, sed'den farklı olarak , işleme başlamak için son satıra ulaşması gerekmeyecek

ile bash , yavaş

while read line; do printf "%s" "$line "; done < file

ile Perl , sed benzeri hızı

perl -p -e 's/\n/ /' file

ile tr , daha hızlı sed , bir karakter yerine sadece

tr '\n' ' ' < file

ile macun , tr -like hız, bir karakter yerine sadece

paste -s -d ' ' file

ile awk'ın , tr benzeri hızlı

awk 1 ORS=' ' file

"Echo $ (<file)" gibi diğer alternatifler yavaştır, yalnızca küçük dosyalar üzerinde çalışır ve işleme başlamak için tüm dosyayı işlemesi gerekir.


Sed'den uzun cevap SSS 5.10

5.10. \ N Escape
dizisini kullanarak neden bir yeni satırı eşleştiremiyorum veya silemiyorum ? Neden \ n kullanarak 2 veya daha fazla satırı eşleştiremiyorum?

\ N hiçbir zaman satır sonundaki satırsonu ile eşleşmeyecektir, çünkü
satır
desen alanına yerleştirilmeden önce satırsonu her zaman çıkarılır . Desen alanına 2 veya daha fazla satır girmek için
, 'N' komutunu veya benzer bir şeyi kullanın ('H; ...; g;' gibi).

Sed şu şekilde çalışır: sed her seferinde bir satır okur, sondaki
yeni satırı keser
, sed komut dosyasının adresleyebileceği veya değiştirebileceği desen alanına kalanları koyar ve desen alanı
yazdırıldığında stdout'a yeni bir satır ekler (veya bir dosyaya). Eğer
model alanı tamamen veya kısmen 'd' ve 'D' ile silinmiş olan,
yeni satır olduğunu olmayan bu gibi durumlarda ilave edildi. Böylece, komut dosyaları

  sed 's/\n//' file       # to delete newlines from each line             
  sed 's/\n/foo\n/' file  # to add a word to the end of each line         

ASLA işe yaramaz, çünkü çizgi desen alanına yerleştirilmeden önce sondaki satırsonu kaldırılır
. Yukarıdaki görevleri gerçekleştirmek için, aşağıdaki
komut dosyalarından birini kullanın:

  tr -d '\n' < file              # use tr to delete newlines              
  sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlines             
  sed 's/$/ foo/' file           # add "foo" to end of each line          

GNU sed dışındaki sed sürümlerinin
desen tamponunun boyutu ile ilgili sınırları olduğundan , burada Unix 'tr' yardımcı programı tercih edilecektir.
Dosyanın son satırı bir satırsonu içeriyorsa, GNU sed
bu satırsonu çıktıya ekler ancak diğerlerini siler, tr ise
tüm satırları siler.

İki veya daha fazla satırlık bir bloğu eşleştirmek için 3 temel seçenek vardır:
(1) desen satırına Sonraki satırı eklemek için 'N' komutunu kullanın;
(2) geçerli satırı
Bekletme alanına eklemek için 'H' komutunu en az iki kez kullanın ve ardından çizgileri
x, g veya G ile bekletme alanından alın ; veya (3)
belirtilen iki adres arasındaki satırları eşleştirmek için adres aralıklarını kullanın (bkz. bölüm 3.3, yukarıdaki) .

Seçenekler (1) ve (2), desen alanına
istenen şekilde adreslenebilecek bir \ n yerleştirir ('s / ABC \ nXYZ / alphabet / g'). Bir
satır bloğunu silmek için 'N' kullanımına örnek olarak bölüm 4.13'te
(" Ardışık belirli satır bloğunu nasıl silebilirim ?") Görünür. Bu
örnek, delete komutunu
'p' (yazdır), 'i' (ekle), 'c' (değiştir), 'a' (ekle)
veya 's' (yerine) gibi başka bir şeye değiştirerek değiştirilebilir. .

Choice (3) bir \ n desen uzaya koymak olmaz, ancak o yok
o değil mi olabilir, böylece üst üste çizgilerin bir blok maç
bile gerek \ n aradığınızı bulmak için. GNU sed
sürüm 3.02.80 artık bu sözdizimini desteklediğinden:

  sed '/start/,+4d'  # to delete "start" plus the next 4 lines,           

geleneksel '/ buradan /, / oraya / {...}' aralık
adreslerine ek olarak, \ n kullanımından tamamen kaçınmak mümkün olabilir.


6
trharika bir fikirdi ve genel kapsamınız yüksek kaliteli bir yanıt getiriyor.
Yeni İskenderiye

1
Kullanmak için +1 ( standart yardımcı program ) paste... ve diğerleri!
Mart'ta Totor


4
Bu cevabın en iyi yanı, "uzun cevap" komutunun nasıl ve neden çalıştığını tam olarak açıklamasıdır.
pdwalker

3
Bu, stackexchange'te okuduğum binlerce cevabın en yararlısı olabilir. Satırlar arasında birden fazla karakteri eşleştirmem gerekiyor. Birden fazla satırı kapsayan önceki sed örnekleri yok ve tr birden fazla karakter eşleşmesini işleyemiyor. Perl iyi görünüyor, ama beklediğim gibi çalışmıyor. Yapabilseydim bu cevabı birkaç kez oylardım.
mightypile

225

Daha kısa bir awk alternatifi:

awk 1 ORS=' '

açıklama

Bir awk programı, koşullu kod bloklarından oluşan kurallardan oluşur, yani:

condition { code-block }

Kod bloğu atlanırsa, varsayılan kullanılan geçerli: { print $0 }. Böylece, 1gerçek bir koşul olarak yorumlanır ve print $0her satır için yürütülür.

Ne zaman awkdeğerine kayıtlarına bunu böler girdi bazlı okurRS varsayılan olarak yeni satır (Tutanak Ayırıcı), böylece awkwill giriş ayrıştırma varsayılan olarak hat-bilge. Bölme ayrıca RSgiriş kaydından çıkarmayı da içerir .

Şimdi, bir kaydı yazdırırken, ORS(Çıktı Kayıt Ayırıcı) ona eklenir, varsayılan yine yeni satırdır. Böylece ORSbir boşluğa geçerek tüm yeni satırlar boşluk olarak değiştirilir.


5
Diğerlerinden çok daha okunabilir olan bu basit çözümü çok seviyorum
Fedir RYKHTIK

8
Daha mantıklı yapıyorsa, bu durum olarak yazılmış olabilir: awk 'BEGIN { ORS=" " } { print $0 } END { print "\n"} ' file.txt(sadece başlangıcı / sonu göstermek için bir bitiş yeni satır ekleme); "1" true(çizgiyi işlemek) ve print(çizgiyi yazdırmak) olarak değerlendirilir. Bu ifadeye bir koşul eklenebilir, örneğin yalnızca bir desenle eşleşen satırlarda çalışma: awk 'BEGIN { ORS=" " } /pattern/ { print $0 } END { print "\n"} '
michael

2
Daha fazlasını yapabilirsiniz simle: codeawk 'ORS = ""' file.txtcode
Udi

Bunun gibi awk kullanılırken maalesef dosyadaki son satır beslemesi de silinir. Kedi dosyası gibi bir alt kabukta 'tr' kullanma hakkında yukarıdaki Patrick Dark cevabına bakın | echo $ (tr "\ 012" "") `hile yapar. Şık.
Bernie Reiter

143

gnu sed, -zboş ayrılmış kayıtlar (satırlar) için bir seçeneğe sahiptir . Sadece şunu arayabilirsiniz:

sed -z 's/\n/ /g'

4
Giriş boş değer içeriyor olsa bile, bunlar (kayıt sınırlayıcılar olarak) korunur.
Toby Speight

6
Hiç boş değer yoksa girişin tamamı yüklenmeyecek mi? Bu durumda, çok gigabaytlık bir dosyanın işlenmesi zor olabilir.
Ruslan

3
@Ruslan, evet tüm girdiyi yükler. Bu çözüm, çok gigabaytlık dosyalar için iyi bir fikir değildir.
JJoao

7
Bu gerçekten en iyi cevap. Diğer ifadeler hatırlanamayacak kadar eğilmiş. @JJoao ile kullanabilirsiniz -u, --unbuffered. manBüyücü devletler: "girdi dosyalarından veri asgari miktarda yük ve daha sık çıkış tamponlarını flush".
not2qubit

yani. çok. bu.
19'da sjas

85

Perl sürümü beklenen şekilde çalışır.

perl -i -p -e 's/\n//' file

Yorumlarda belirtildiği gibi, bu düzenlemenin yerinde olduğunu belirtmek gerekir. normal ifadenizin düşündüğünüz kadar akıllı olmaması -i.bakdurumunda, değiştirilmeden önce orijinal dosyanın yedeğini alırsınız.


23
Lütfen en azından -ibir sonek olmadan hiçbir yedekleme olmadığını belirtin . -i.baksizi kolay, çirkin bir hatadan korur (örneğin, -pdosyayı yazmayı ve sıfırlamayı unutmak ).
Telemachus

6
@Telemachus: Bu adil bir nokta, ama her iki şekilde de tartışılabilir. Bahsetmediğim ana sebep, OP'nin sorusundaki sed örneğinin yedekleme yapmamasıdır, bu yüzden burada gereksiz görünüyor. Diğer nedeni, aslında yedekleme işlevselliğini hiç kullanmadım (aslında otomatik yedekleri sinir bozucu buluyorum), bu yüzden her zaman orada olduğunu unutuyorum. Üçüncü neden, komut satırımı dört karakter daha uzatması. Daha iyi veya daha kötü (muhtemelen daha kötü) için, ben zorlayıcı bir minimalistim; Ben sadece kısalığı tercih ederim. Kabul etmediğinizin farkındayım. Gelecekte yedeklemeler hakkında uyarmayı hatırlamak için elimden geleni yapacağım.
ire_and_curses

6
@Ire_and_curses: Aslında, beni görmezden geldiğin için iyi bir tartışma yaptın. Yani, seçimleriniz için nedenleriniz var ve seçimlere katılıp katılmamam, kesinlikle buna saygı duyuyorum. Tamamen neden olduğundan emin değilim, ama son zamanlarda bu özel şey hakkında bir gözyaşı döktüm ( -iPerl'deki soneksiz bayrak). Yakında takıntılı başka bir şey bulacağımdan eminim. :)
Telemachus

-Dosya adı belirterek bunun stdin ile çalışmaması gerçekten talihsiz bir durumdur . Bunu yapmanın bir yolu var mı? Bir dosyayı değiştirmekten endişe etmemenin yolu kedi ile başlayan bir boru hattı kullanıyor.
Steven Lu

@StevenLu Perl varsayılan olarak STDIN'den dosya adı verilmezse okunur. Yani örneğin yapabilirsinperl -i -p -e 's/\n//' < infile > outfile
ire_and_curses

44

Kimin ihtiyacı var sed? İşte bashyolu:

cat test.txt |  while read line; do echo -n "$line "; done

2
Upvote, normalde en iyi cevabı kullandım, ancak / dev / urandom üzerinden boru kullanırken, sed EOF olana kadar yazdırılmaz ve ^ C EOF olmaz. Bu çözüm her yeni satır gördüğünde yazdırılır. Tam olarak ihtiyacım olan şey! Teşekkürler!
Vasiliy Sharapov

1
o zaman neden olmasın: echo -n `cat days.txt` Bu yazıda
Tony

9
@Tony, backticks kullanımdan kaldırıldığı ve kedi gereksiz olduğu için ;-) Kullanım: echo $ (<days.txt)
seumasmac

10
Hatta kullanmadan cat: while read line; do echo -n "$line "; done < test.txt. Bir alt kabuk sorunsa faydalı olabilir.
Carlo Cannas

5
echo $(<file)tüm boşlukları sadece yeni satırlara değil, tek bir alana sıkıştırır : bu OP'nin istediklerinin ötesine geçer.
glenn jackman

27

Tüm satırları belleğe okumadan awk kullanan boşluklarla değiştirmek için:

awk '{printf "%s ", $0}' inputfile

Son satırsonu istiyorsanız:

awk '{printf "%s ", $0} END {printf "\n"}' inputfile

Boşluk dışında bir karakter kullanabilirsiniz:

awk '{printf "%s|", $0} END {printf "\n"}' inputfile

END{ print ""}sondaki satırsonu için daha kısa bir alternatiftir.
Isaac

22
tr '\n' ' ' 

komuttur.

Basit ve kullanımı kolaydır.


14
ya da sadece tr -d '\n'bir boşluk eklemek istemiyorsanız
spuder

21

Üç şey.

  1. tr(veya catvb.) kesinlikle gerekli değildir. (GNU) sedve (GNU) awkbirleştirildiğinde, ihtiyacınız olan metin işlemlerinin% 99,9'unu yapabilir.

  2. stream! = satır tabanlı. edsatır tabanlı bir editördür. seddeğil. Fark hakkında daha fazla bilgi için sed dersine bakın . Çoğu kişi sedsatır tabanlı olmayı karıştırır , çünkü varsayılan olarak BASİT eşleşmeleri için desen eşleşmesinde çok açgözlü değildir - örneğin, desen araması yaparken ve bir veya iki karakterle değiştirirken, varsayılan olarak yalnızca ilk eşleşmenin yerine geçer bulur (global komut tarafından aksi belirtilmedikçe). STREAM tabanlı olmaktan ziyade satır tabanlı olsaydı küresel bir komut bile olmazdı, çünkü aynı anda sadece satırları değerlendirecekti. Koşmayı deneyin ed; farkı göreceksiniz. edbelirli satırlar (örneğin bir for-loop'ta) üzerinde yineleme yapmak istiyorsanız, ancak çoğu zaman istediğinizde oldukça kullanışlıdır sed.

  3. Söyleniyor ki,

    sed -e '{:q;N;s/\n/ /g;t q}' file
    

    GNU sed4.2.1 sürümünde gayet iyi çalışıyor . Yukarıdaki komut tüm yeni satırları boşluklarla değiştirecektir. Yazmak çirkin ve biraz hantal, ama gayet iyi çalışıyor. {}Onlar sadece aklı nedenlerle dahil ediyoruz olarak 'ler, dışarıda bırakılabilir.


3
Sadece yeterince bilen bir kişi olarak sedtemel şeyler, ben daha ne hakkında daha olduğunu söylemek zorunda olabilir ilgisi sedfakat ne olup bittiğini anlamak için oldukça ne kadar kolay. Ben çalışırken sedçok daha basit bir komut tercih ederim ile çalışmak çok zor bir zaman var.
Nate

t qKoşullu atlama olarak kullanmak s/\n / /, tüm dosyayı belleğe okumadan (boşlukla başlayan tüm satırları birleştirmek için) gibi bir desenle çalışır . Çoklu megabayt dosyaları dönüştürürken kullanışlıdır.
textshell

Bağlantı
verdiğiniz makale

Bu büyük girdide kabul edilen cevaptan neredeyse 800 kat daha yavaştır. Bunun nedeni, gittikçe daha büyük girdilerdeki her satırın yerine geçen çalıştırmadır.
Thor

13

İle cevap: bir etiket ...

Sed kullanarak bir satırsonu (\ n) nasıl değiştirebilirim?

... komut satırındaki freebsd 7.2'de çalışmaz:

(yankı foo; yankı çubuğu) | sed ': a; N; $! ba; s / \ n / / g'
sed: 1: ": a; N; $! ba; s / \ n / / g": kullanılmayan etiket 'a; N; $! ba; s / \ n / / g'
foo
bar

Eğer sed komut dosyasını bir dosyaya koyarsanız veya sed komut dosyasını "oluşturmak" için -e kullanırsanız ...

> (echo foo; echo bar) | sed -e: a -e N -e '$! ba' -e 's / \ n / / g'
foo bar

veya ...

> cat > x.sed << eof
:a
N
$!ba
s/\n/ /g
eof

> (echo foo; echo bar) | sed -f x.sed
foo bar

Belki OS X'teki sed benzerdir.


-E argümanları dizisi benim için MKS kullanarak pencerelerde çalıştı! Teşekkürler!
JamesG

12

Anlaması Kolay Çözüm

Bu sorunu yaşadım. En önemlisi BSD'ler (Mac OS X) ve GNU'lar (Linux ve Cygwin ) üzerinde çalışmak için çözüme ihtiyaç duymamdısed ve tr:

$ echo 'foo
bar
baz


foo2
bar2
baz2' \
| tr '\n' '\000' \
| sed 's:\x00\x00.*:\n:g' \
| tr '\000' '\n'

Çıktı:

foo
bar
baz

(sondaki satırsonu vardır)

Linux, OS X ve BSD üzerinde çalışır - UTF-8 desteği olmadan veya crappy terminali ile bile .

  1. Yeni trsatırı başka bir karakterle değiştirmek için kullanın .

    NULL( \000veya \x00) güzeldir, çünkü UTF-8 desteğine ihtiyaç duymaz ve kullanılması muhtemel değildir.

  2. sedEşleştirmek için kullanınNULL

  3. trİhtiyacınız olursa ekstra satırları değiştirmek için kullanın


1
Nomenklatür üzerine ince bir not: karakter \000genellikle NUL(bir L) olarak adlandırılır ve NULLgenellikle bir sıfır işaretçisi hakkında konuşurken kullanılır (C / C ++ 'da).
sqweek


9

Ben uzman değilim ama sanırım sedilk önce desen alanına bir sonraki satırı eklemeniz gerekecek, " N" kullanarak bij . Sed & awk kitabının "Gelişmiş sed Komutları" bölümündeki "Çok Satırlı Desen Alanı" bölümünden (Dale Dougherty ve Arnold Robbins; O'Reilly 1997; önizlemede sayfa 107 ):

Çok satırlı Next (N) komutu, yeni bir girdi satırı okuyarak ve onu kalıp alanının içeriğine ekleyerek çok satırlı bir kalıp alanı oluşturur. Desen alanının orijinal içeriği ve yeni giriş çizgisi, yeni satırla ayrılır. Katıştırılmış yeni satır karakteri kaçış dizisi "\ n" ile desenlerle eşleştirilebilir. Çok satırlı bir desen alanında, "^" meta karakteri, herhangi bir gömülü yeni satırı / çizgiyi takip eden karakter (ler) ile değil, desen alanının ilk karakteriyle eşleşir. Benzer şekilde, "$", kalıp uzayındaki yalnızca son satırsonu ile eşleşir, gömülü satır (lar) ile aynı değildir. Sonraki komut yürütüldükten sonra, denetim komut dosyasında sonraki komutlara geçirilir.

Gönderen man sed:

[2addr] N-

Eklenen materyali orijinal içeriklerden ayırmak için katıştırılmış yeni satır karakteri kullanarak desen alanına bir sonraki girdi satırını ekleyin. Geçerli satır numarasının değiştiğini unutmayın.

Ben ettik bu kullanılan arama dizesi bir "yetim" sonraki satırda bulunabilir hangi kötü biçimlendirilmiş günlük dosyalarını, (çok sayıda) aramak için.


7

Yeni satırları sekmelerle değiştirmek için tr'i kullanarak satırları değiştirmek için hibrit bir yaklaşım kullandım, ardından sekmeleri istediğim şeyle değiştirdim. Bu durumda, "
" HTML sonları oluşturmaya çalışıyorum.

echo -e "a\nb\nc\n" |tr '\n' '\t' | sed 's/\t/ <br> /g'`

6

Yukarıdaki "tr" çözümüne yanıt olarak, Windows'ta (muhtemelen tr'in Gnuwin32 sürümünü kullanıyor), önerilen çözüm:

tr '\n' ' ' < input

benim için çalışmıyorsa, bir nedenden dolayı ya hata ya da aslında \ nw / '' yerine geçerdi.

Tr başka bir özelliğini kullanarak, "delete" seçeneği -d olsa da işe yaradı:

tr -d '\n' < input

veya '\ n' yerine '\ r \ n'


3
Windows'da muhtemelen kullanmanız gerekir tr "\n" " " < input. Windows kabuğu (cmd.exe) kesme işaretini tırnak işareti olarak görmez.
Keith Thompson

Hayır, Windows 10 Ubuntu alt sisteminde kullanmanız gerekirtr "\n\r" " " < input.txt > output.txt
user1491819

Bu GnuWin32 kullanarak, Windows 10 üzerinde çalışır: cat SourceFile.txt | tr --delete '\r\n' > OutputFile.txt. Veya Gnuwin32 yerine Gow'u (Windows'ta Gnu) kullanın, github.com/bmatzelle/gow/wiki
Alchemistmatt

5

Kurşun geçirmez çözüm. İkili veri güvenli ve POSIX uyumlu, ancak yavaş.

POSIX sed , POSIX metin dosyasına ve POSIX satırına göre giriş gerektirir tanımlarına , bu nedenle NULL bayt ve çok uzun satırlara izin verilmez ve her satır bir satırsonu (son satır dahil) ile bitmelidir. Bu, sed'in rastgele giriş verilerinin işlenmesi için kullanılmasını zorlaştırır.

Aşağıdaki çözüm sed'den kaçınır ve bunun yerine girdi baytlarını sekizlik kodlara ve sonra tekrar baytlara dönüştürür, ancak sekizlik kodu 012'yi (satırsonu) durdurur ve yerine yeni bir dize çıkarır. Çözümün POSIX uyumlu olduğunu söyleyebildiğim kadarıyla çok çeşitli platformlarda çalışması gerekir.

od -A n -t o1 -v | tr ' \t' '\n\n' | grep . |
  while read x; do [ "0$x" -eq 012 ] && printf '<br>\n' || printf "\\$x"; done

POSIX referans belgeleri: sh , kabuk komut dili , od , tr , grep , read , [ , printf .

Hem read, [ve printfen azından bash gömmeler, ama bu muhtemelen bu yüzden bazı platformlarda her giriş bayt şeyler yavaşlatır, bir veya daha fazla yeni süreçler başlayacak olması olabilir, POSIX tarafından garanti edilmez. Bash'da bile bu çözüm sadece yaklaşık 50 kB / s'ye ulaştığından, büyük dosyalar için uygun değildir.

Ubuntu (bash, tire ve busybox), FreeBSD ve OpenBSD üzerinde test edildi.


5

Bazı durumlarda belki RSbaşka bir dizgiye veya karaktere geçebilirsiniz . Bu şekilde, \ n alt / gsub için kullanılabilir:

$ gawk 'BEGIN {RS="dn" } {gsub("\n"," ") ;print $0 }' file

Kabuk kodlamanın gücü, bir şekilde nasıl yapılacağını bilmiyorsanız, başka bir şekilde yapabileceğinizdir. Ve çoğu zaman, basit bir soruna karmaşık bir çözüm yapmaktan daha fazla dikkate almanız gerekir.

Gawk'ın yavaş olduğu ve dosyayı belleğe okuduğu şeyle ilgili olarak, bunu bilmiyorum, ama bana göre gawk o sırada bir satırla çalışıyor gibi görünüyor ve çok hızlı (diğerlerinden o kadar hızlı değil) , ancak yazma ve test etme süresi de önemlidir).

MB ve hatta GB veri işliyorum ve bulduğum tek sınır satır boyutu.


5

Windows satır sonları ile uğraşmak için yeterince talihsiz iseniz \rve\n

tr '[\r\n]' ' ' < $input > $output

Bu [, bir boşluk, \rbir boşluk, \nbir boşluk ve ]bir boşluk ile değiştirilir. tr -d '\r\n' <fileherhangi bir karakteri \rveya \nkarakteri kaldıracaktı , ama aynı zamanda istenen de bu değil. muhtemelen kullanışlı olmaya daha yakın olan ve muhtemelen OP'nin ihtiyacı için doğru olan (yine de bu ters eğik çizgiyi anladığınızı varsayarak) tr -d '\r' <filetüm \rkarakterleri (bitişik olup olmadıklarına bakılmaksızın) kaldıracaktır . \ntr
tripleee

4

Kullanabilirsiniz xargs- yerini alacak\n varsayılan olarak bir boşlukla .

Ancak, girdinizde herhangi bir durum unterminated quotevarsa, örneğin belirli bir satırdaki tırnak işaretleri uyuşmuyorsa sorun yaşayabilir .


xargs ayrıca son satırı güzelce ele alıyor:
AAAfarmclub

4

Allow komutunu kullanarak bulur ve değiştirir \ n

sed -ie -z 's/Marker\n/# Marker Comment\nMarker\n/g' myfile.txt

İşaretleyici

Oluyor

# Marker Yorumu

İşaretleyici


4

Neden basit bir çözüm bulamadım awk?

awk '{printf $0}' file

printf orijinal satırları boşluk veya başka bir satırla ayırmak istiyorsanız, her satırı yeni satırlar olmadan yazdıracaktır:

awk '{printf $0 " "}' file

echo "1\n2\n3" | awk '{printf $0}', bu benim için çalışıyor. @ edi9999
Itachi

Haklısınız üzgünüm, ben unuttum ediyoruz fprintf'teki
edi9999

bu benim için git bash içinde windows için çalışan tek yaklaşımdı
Plato

3

Mac OS X'te (FreeBSD sed kullanarak):

# replace each newline with a space
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g; ta'
printf "a\nb\nc\nd\ne\nf" | sed -E -e :a -e '$!N; s/\n/ /g' -e ta


3

Awk kullanma:

awk "BEGIN { o=\"\" }  { o=o \" \" \$0 }  END { print o; }"

2
Dış işaretleri tek tırnak işareti olarak değiştirirseniz, tırnak işaretlerinden ve dolar işaretinden kaçmanıza gerek yoktur. "0" harfi genellikle "0" rakamıyla karıştırılabileceğinden değişken adı olarak kötü bir seçim olarak kabul edilir. Ayrıca değişkeninizi başlatmanıza gerek yoktur, varsayılan olarak boş bir dize olur. Ancak, eğer bir yabancı lider boşluğu istemiyoruz: awk '{s = s sp $0; sp = " "} END {print s}'. Ancak, tüm dosyayı belleğe okumadan awk kullanmanın bir yolu için cevabımı görün.
sonraki duyuruya kadar duraklatıldı.

Lütfen bunun yerine Thor'un cevabını kontrol edin . Bu şekilde daha verimli, okunabilir ve adildir daha iyi karşılaştırıldığında bu yaklaşımın (bu halde bütün yollarla olur çalışmak)!
mschilli

Dostum, anladım. Yüzüme ovalamaya gerek yok :-) Thor'un cevabı yine de sayfada (yolun üstünde) yukarıda, bu yüzden ne umursuyorsun?
kralyk

3

Özellikle sevdiğim bir çözüm, bekletme alanındaki tüm dosyaları eklemek ve dosyanın sonundaki tüm yeni satırları değiştirmek:

$ (echo foo; echo bar) | sed -n 'H;${x;s/\n//g;p;}'
foobar

Ancak, birisi bana bazı boş uygulamalarda tutma alanının sonlu olabileceğini söyledi.


1
cevabınızdaki boş bir dize ile değiştirme, tutma alanına eklemek için her zaman H kullanmanın, tutma alanının bir satırsonu ile başlayacağı anlamına gelir. Bundan kaçınmak için kullanmanız gerekir1h;2,$H;${x;s/\n/x/g;p}
Jeff

3

Yeni satırları herhangi bir dize ile değiştir ve son yeni satırı da değiştir

Saf trçözümler yalnızca tek bir karakterle değiştirilebilir ve saf sedçözümler, girdinin son satırsonunun yerini almaz. Aşağıdaki çözüm bu sorunları giderir ve ikili veriler (UTF-8 yerel ayarında bile) için güvenli gibi görünür:

printf '1\n2\n3\n' |
  sed 's/%/%p/g;s/@/%a/g' | tr '\n' @ | sed 's/@/<br>/g;s/%a/@/g;s/%p/%/g'

Sonuç:

1<br>2<br>3<br>

Bu kötüdür, çünkü herhangi bir girdide istenmeyen çıktılar üretecektir@
Steven Lu

@StevenLu: Hayır, @girişte sorun yok. Tekrar kaçar %a. Çözüm tamamen POSIX uyumlu olmayabilir (NULL baytlara izin verilmez, bu nedenle ikili veriler için iyi değildir ve tüm satırlar yeni satırla bitmelidir, böylece trçıktı gerçekten geçerli değildir).
Håkon A. Hjortland

Ah. Gördün mü, tamir ettin. Basit bir işlem olması gereken şey için kıvrık, ama iyi iş çıkardı.
Steven Lu

3

Bu sed olduğunu tanıtır "normal" oyuncu değişikliğinden sonra yeni hatlar. İlk olarak, yeni satır karakterini keser, daha sonra talimatlarınıza göre işler, sonra yeni bir satır sunar.

Sed kullanarak , her giriş satırı için, kesildikten sonra bir satırın "sonunu" (yeni satır karakterini değil) istediğiniz bir dizeyle değiştirebilirsiniz; ancak sed farklı satırlar çıkarır . Örneğin, "satır sonu" nu "===" (tek bir boşlukla değiştirmekten daha genel) ile değiştirmek istediğinizi varsayalım:

PROMPT~$ cat <<EOF |sed 's/$/===/g'
first line
second line
3rd line
EOF

first line===
second line===
3rd line===
PROMPT~$

Dizeyle satır kömürü değiştirmek için, verimsiz olsa, kullanım olabilir tr , daha önce sivri, sonra kullanın "özel char" ile yeni satır-karakter değiştirip için sed istediğiniz dizeyle bu özel kömürü yerine .

Örneğin:

PROMPT~$ cat <<EOF | tr '\n' $'\x01'|sed -e 's/\x01/===/g'
first line
second line
3rd line
EOF

first line===second line===3rd line===PROMPT~$

3

Bu yöntemi de kullanabilirsiniz

sed 'x;G;1!h;s/\n/ /g;$!d'

açıklama

x   - which is used to exchange the data from both space (pattern and hold).
G   - which is used to append the data from hold space to pattern space.
h   - which is used to copy the pattern space to hold space.
1!h - During first line won't copy pattern space to hold space due to \n is
      available in pattern space.
$!d - Clear the pattern space every time before getting next line until the
      last line.

Akış:
İlk satır girişten alındığında, değişim yapılır, böylece 1 boşluk tutmaya gider ve \ n desen boşluğuna gelir, daha sonra tutma boşluğunu desen boşluğuna ekler ve sonra yerine koyma gerçekleştirilir ve desen boşluğunu siler.
İkinci satır değişimi yapılırken, 2 boşluk tutmaya gider ve 1 desen boşluğuna gelir, daha sonra Gtutma boşluğunu desen boşluğuna ekler, ardından hdeseni kopyalar ve yerine koyma yapılır ve silinir. Bu işleme eof değerine ulaşılana kadar devam edilir, ardından kesin sonuç yazdırılır.


Ancak, uyarılmak echo 'Y' | sed 'x;G;1!h;s/\n/X/g;$!d'sonuçları XY.
Ürkütücü

3

Zsolt Botykai'nin cevabı ile hemen hemen aynı olan başka bir GNU sed yöntemi, ancak bu, bir bayt kod ( arkadaki) kaydedilensed daha az kullanılan y( harf çevirisi ) komutunu kullanır :g

sed ':a;N;$!ba;y/\n/ /'

Biri daha yhızlı s, belki de tr20x daha hızlı çalışır, ancak GNU sed v4.2.2'den y yaklaşık % 4 daha yavaş çalışır s.


Daha taşınabilir BSD sed sürümü:

sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'

2
BSD sed yile yaklaşık% 15 daha hızlıdır. Çalışan bir örnek için bu cevaba bakınız .
Thor

Ayrıca, BSD sed komutları bir etiket sonra sona ermesi gerekir, bu yüzden sed -e ':a' -e 'N;$!ba' -e 'y/\n/ /'gitmek için yol olacaktır.
ghoti
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.