Sed yeni satır karakterlerinin yerini alabilir mi?


42

Sed ve yeni çizgi karakteriyle ilgili bir sorun mu var?
Aşağıdaki içeriklere sahip bir test.txt dosyasına sahibim

aaaaa  
bbbbb  
ccccc  
ddddd  

Aşağıdaki çalışmıyor:
sed -r -i 's/\n/,/g' test.txt

Bunun triçin kullanabileceğimi biliyorum ama sorum, sed ile neden mümkün görünmediği.

Bu, dosya satır satır işlemenin bir yan etkisi ise, bunun neden olduğunu merak ediyorum. Bence grepyeni çizgileri kaldırıyor. Sed aynı şeyi yapar mı?


1
Bu durumda sed, kullanılacak en iyi araç olmayabilir (örn. "Tr"). Daha sezgisel, okuması kolay / bakımı kolay, daha iyi performans gösteren (özellikle büyük verilerde) vb. Araçlar var. Bir karşılaştırma bulabilirsiniz: http://slash4.de/blog/python/sed-replace-newline-or-python-awk-tr-perl-xargs.html
omoser

2
trbir iz ekler ,ve sonlandırılmamış bir çizgi çıkarırdı. pasteBunun yerine kullanmak en iyisi :paste -sd , test.txt
Stéphane Chazelas

Yanıtlar:


48

GNU sedile sağlanan POSIXLY_CORRECTve ortamda değil (tek satırlık giriş için):

sed -i ':a;N;$!ba;s/\n/,/g' test.txt

Gönderen https://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-n :

  1. üzerinden bir etiket oluştur :a
  2. geçerli ve bir sonraki satırı desen boşluğuna ekleme N
  3. eğer son satırdan önce olursak, oluşturulan etikete dallanır $!ba( $!son satırda bunu yapmamak anlamına gelir (bir son satırsonu olması gerektiği gibi)).
  4. Sonunda oyuncu değişikliği her yeni satırın yerini (boşluk dosyasının tamamı) kalıp uzayındaki virgül ile değiştirir.

Bu, sed sorun bu bir issue.It neden sadece çizgi okumak ve, yeni satır karakterini (veya son karakteri) yerine geçebilecek anlayamıyorum line.But I tarafından satır okur belirtmek görünüyor
Jim

1
@jim Eşleşecek arabellekte yok gibi görünüyor, ama ben sed ile akıcı değilim, belki birileri buna ışık tutabilir. Bence Q'nuzu bu özel bilgilerle genişletmelisiniz, bu yüzden insanlar onu okumak ve umarım cevap vermek için daha muhtemeldir.
Anthon

Bu daba: Event not found
krb686

@ krb686 Bahsettiğiniz "Bu" nedir? Yukarıdaki sedkomutu tam olarak bu seçeneklerle çalıştırdınız mı? Hangi test.txt dosyada? Hangi sürümüyle sed(deneyin sed --version)?
Anthon

@Anthon Üzgünüm, sanırım "" demek istedim. Csh'ın benden kaçmamı istediğini bildiren bir başka SO yazısı okudum !. İlginçtir, bu yine de benim için iş vermedi ve ben kaçmak iki katına sahip bitti !benim de .cshsenaryo. Yani şu anda gerçekten bir sorunum yok, ama bunun neden olabileceğini biliyor musun? Benim için ne çalıştısed :a;N;$\\!ba;s/\n/ /g'
krb686

16

Bu GNU ile çalışır sed:

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

-z 4.2.2'den beri dahil edilmiştir

NB. -zsınırlayıcıyı boş karakterlere ( \0) değiştirir. Girişiniz boş karakter içermiyorsa, girişin tamamı tek satır olarak değerlendirilir. Bu onun sınırlamaları ile gelebilir .

Son satırın yeni satırının değiştirilmesini önlemek için tekrar değiştirebilirsiniz:

sed -z 's/\n/,/g;s/,$/\n/'

(Hangi GNU sedsözdizimi yine, ama her şey sadece GNU olduğu gibi önemli değil)


3
Bu aynı zamanda OP'nin istediği gibi olmayabilecek izleyen yeni hattın yerini alacak ... sonucu mikeserv'in çözümüyle karşılaştırın.
don_crissti

7

Oracle web sitesinden:

Sed yardımcı programı, bir dosyayı satır satır belleğe sırayla okuyarak çalışır. Ardından, hat için belirtilen tüm eylemleri gerçekleştirir ve istenen değişiklikleri yapılan terminale dökmek için satırı belleğe geri koyar. Tüm işlemler bu satırda gerçekleştikten sonra, dosyanın sonraki satırını okur ve dosya ile bitene kadar işlemi tekrarlar.

Temel olarak bu, sed'nin satır satır okuduğu için yeni satır karakterinin eşleşmediği anlamına gelir.

Https://stackoverflow.com/questions/1251999/sed-how-can-i-replace-a-newline-n adresindeki çözüm şöyledir:

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

veya, taşınabilir bir versiyonda ( ;atlama işareti etiketlerinden sonra birleştirme olmadan )

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

Bu sayfada nasıl çalıştığına dair bir açıklama verilmiştir.


VPN günlüklerini ayrıştırmak ve kullanıcıyı "kimliği doğrulanmış" ve zaman damgası bilgilerini aynı satıra koymak için bunun değiştirilmiş bir formunu kullandım. Şerefe!
user208145

Sözdiziminin sedGNU'ya özgü olduğunu ve hatta POSIXLY_CORRECT'in çevrede olması ve girişin yalnızca bir satır olması durumunda GNU'da bile bir çıktı olmayacağını unutmayın.
Stéphane Chazelas,

5

sed\ndesen boşluğunu doldurmadan hemen önce her zaman sonunu ewline kaldırır ve sonra komut dosyasının sonuçlarını yazmadan önce bir tane ekler. Bir \newline desen alanı içinde çeşitli yollarla olabilir - ancak asla bir düzenlemenin sonucu değilse. Bu önemlidir - desen alanındaki \newlines sedher zaman bir değişikliği yansıtır ve giriş akışında asla gerçekleşmez. \newlines, bir der'in sedbilinmeyen bir giriş ile güvenebileceği tek sınırlayıcıdır .

Tüm \nsatırları virgüllerle değiştirmek istiyorsanız ve dosyanız çok büyük değilse, şunları yapabilirsiniz:

sed 'H;1h;$!d;x;y/\n/,/'

Bu h, ewline karakterini hizleyen her giriş satırını eski boşluğa ekler \n; Daha sonra dçıktıdan sonuncu olmayan her satırı siler $!. Son satırda Heski ve kalıp boşlukları xdeğiştirilir ve tüm \nsatır satırı karakterleri y///virgüllere çevrilir.

Büyük dosyalar için, bu tür bir sorun sed, bu tür eylemlerle kolayca taşabilen çizgi sınırlarındaki arabellek sorunlarına neden olmak zorundadır.


2

Alternatif olarak, biraz daha basit bir sözdizimi kullanabilirsiniz:

sed ':a;N;s/\n/,/g;ba'

... sadece sıra sırasını değiştiriyorum.


3
Ancak, sher giriş satırı için komutu, giderek daha büyük olan bir desen alanı üzerinde çalıştırır .
Stéphane Chazelas

1

Bazı çok güzel Orada sed burada büyü. Ve desen alanı taşması hakkında bazı iyi noktalar gündeme geldi. En basit yol olmasa bile sed'i kullanmayı seviyorum , çünkü çok kompakt ve güçlü. Bununla birlikte, bunun sınırlamaları vardır ve büyük miktardaki veriler için, kalıp uzayının kısmi olması gerekirdi.

GNU bunu söylüyor:

Portatif sed komut dosyaları yazmak isteyenler için, bazı uygulamaların satır uzunluklarını (desen ve boşluklar için) 4000 bayttan fazla olamayacağının bilindiğini unutmayın. Posix standardı, uygun uygulamaların en az 8192 bayt satır uzunluğunu destekleyeceğini belirtir. GNU sed'nin hat uzunluğu için yerleşik bir sınırı yoktur; malloc () daha fazla (sanal) belleği alabildiği sürece, istediğiniz kadar satır besleyebilir veya oluşturabilirsiniz.
Ancak, özyineleme alt desenleri ve belirsiz tekrarları işlemek için kullanılır. Bu, mevcut yığın alanının belirli kalıplarla işlenebilen arabellek boyutunu sınırlayabileceği anlamına gelir.

Ekleyecek çok şeyim yok, ancak sizi sed -go için rehberime yönlendirmek istiyorum . Bu mükemmel. http://www.grymoire.com/Unix/Sed.html

ve işte benim çözümüm:

for i in $(cat test.txt); do echo -n $i','; done; echo '' >> somewhere

iyi çalışıyor



-1

Yeni satırları ile değiştirmek istediğinizi varsayalım \n. Bunu yapmak istedim, işte yaptığım işte:

(echo foo; echo bar; echo baz) | sed -r '$!s/$/\\n/' | tr -d '\n' 
# Output: foo\nbar\nbaz

İşte ne yaptığı: son hariç, tüm satırlar için sonlandır \n. Ardından, ile yeni satırları silin tr.


-rBSD’de seddeğil, sadece GNU’da kullanılabilir.
kenorb
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.