Bir desenin önüne yeni satır nasıl eklenir?


138

Çizgi içindeki bir desenden önce yeni satır nasıl eklenir?

Örneğin , normal ifadenin arkasına yeni bir satır eklenir.

sed 's/regex/&\n/g'

Aynısını ancak kalıbın önünde nasıl yapabilirim ?

Bu örnek girdi dosyası göz önüne alındığında, eşleşecek kalıp telefon numarasıdır.

some text (012)345-6789

Olmalı

some text
(012)345-6789

Sadece cevabını tekrarlayarak bir çizgi sed kullanarak sonra bir satır / linebreak eklemek nasıl burada:sed '/regex/G'
Adam Schmideg

1
@NilsvonBarth, açık bir soru neden kötü bir soru?
Josh

Yanıtlar:


177

Linux ve OS X'te çalışır bashve zshtest edilir:

sed 's/regexp/\'$'\n/g'

Genel olarak, $tek tırnak içinde bir dizgi değişmezi izleyen bashC-stili ters eğik çizgi yerine koyma gerçekleştirir, örneğin $'\t'değişmez bir sekmeye çevrilir. Ayrıca sed, yeni satırınızın bir ters eğik çizgi ile kaçmasını istiyor, dolayısıyla daha \önce $. Ve son olarak, dolar işaretinin kendisi alıntılanmamalı, böylece kabuk tarafından yorumlanmalı, bu nedenle teklifi daha önce $kapatıp tekrar açıyoruz.

Düzenleme : @ mklement0 tarafından yapılan yorumlarda önerildiği gibi, bu da işe yarar:

sed $'s/regexp/\\\n/g'

Burada olan şey: sed komutunun tamamı artık C stili bir dizedir, yani sed'in yeni satır değişmezinden önce yerleştirilmesi gereken ters eğik çizgi artık başka bir ters eğik çizgiyle kaçılmalıdır. Daha okunabilir olmasına rağmen, bu durumda kabuk dize ikameleri yapamazsınız (tekrar çirkin yapmadan).


7
Bu bana OSX üzerinde "yedek desen içinde kaçan yeni satır" verir.
Matt Gibson

@Matt Gibson bu çok garip çünkü "kaçınılmamış yeni satır" sadece yerine koyma düzeni içinde ters eğik çizgi olmadan gerçek bir yeni satırınız olduğunda verilir. Yukarıdaki kodum aslında diğer bazı kabuklarda da çalışıyor, örn. Zsh, ksh.
mojuba

3
@Matt Gibson ... ya da kodumdaki '$' \ n öncesindeki ters eğimi unutursanız.
mojuba

7
Yazıldığı gibi, bu ifadeler, istendiği gibi mevcut bir satırın ortasına yeni satır eklemek yerine normal ifadeyi tamamen yeni satırla değiştirir. Burada iki eşleşen desenleri arasında bir yeni satır eklemek için bu cevabın değiştirilmiş şekli kullanmış açıklanmıştır: sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'. \ N'den sonraki iki tek tırnak işaretini not edin. Birincisi " $" bölümünü kapatır, böylece hattın geri kalanı bundan etkilenmez. Bu alıntılar olmadan \ 2 önemsenmedi.
David Ravetti

12
Başka bir seçenek kullanmaktır tek ANSI C-alıntılanan dize : sed $'s/regexp/\\\n/g', okunabilirliği artırır - Sadece farkı sonra ihtiyaç vardır katına tüm edebi \ karakter.
mklement0

43

Diğer cevaplardan bazıları sed sürümümde işe yaramadı. Anahtarlama pozisyonu &ve \nçalışma yaptı.

sed 's/regexp/\n&/g' 

Düzenleme: Bu, yüklemediğiniz sürece OS X üzerinde çalışmıyor gibi görünüyor gnu-sed.


9
Bunun sed'in tüm sürümlerinde çalıştığından emin değilim. Bunu Mac'imde denedim ve \ n sadece 'n' olarak çıktı alıyor
Todd Gamblin

3
Cevabınızı okumadan önce işimde mac'ta 15 dakika geçirdim. Apple'a git!
Rick77

1
Homebrew kullananlar için: brew install gnu-sedardındangsed 's/regexp/\n&/g'
aaaaaa

1
... ardındanecho 'alias sed=gsed' >> ~/.bashrc
Proximo

36

Sed'de, çıkış akışına kolayca yeni satırlar ekleyemezsiniz. Garip olan bir devam çizgisi kullanmanız gerekir, ancak işe yarar:

$ sed 's/regexp/\
&/'

Misal:

$ echo foo | sed 's/.*/\
&/'

foo

Ayrıntılar için buraya bakın. Biraz daha az garip bir şey istiyorsanız perl -pe, sed yerine eşleşme gruplarıyla kullanmayı deneyebilirsiniz :

$ echo foo | perl -pe 's/(.*)/\n$1/'

foo

$1 "Parantez" terimi, düzenli ifadedeki grupların parantez içinde olduğu ilk eşleşen grubu belirtir.


Neden satırsonu ekleyemeyeceğinizi söylüyorsunuz? Sadece sed 's / regexp / & \ n / g' yapabilirsiniz Bu kadar
Andres

2
Bu, yeni satır eklemek için bir Mac'te yapabileceğiniz en kötü görünümlü şey (\ n bir
mac'ta çalışmıyor

Perl sürümü yerinde düzenleme yapmak için değiştirilebilirperl -pi -e 's/(.*)/\n$1/' foo
Eponymous

2
@Andres: (Çoğunlukla) Sadece OSIX ile birlikte gelen BSD sürümü gibi POSIX özelliklerine sahip Sed uygulamaları, bir sişlev çağrısının ikame bölümünde kontrol karakteri kaçış dizilerini desteklemez ( GNU Sed uygulamasının aksine ) . Yukarıdaki cevap her iki uygulama için de geçerlidir; tüm farklılıklara genel bir bakış için buraya bakınız .
mklement0

29

Mac bilgisayarımda, aşağıdaki satırsonu yerine tek bir 'n' ekler:

sed 's/regexp/\n&/g'

Bu, newline ile değiştirilir:

sed "s/regexp/\\`echo -e '\n\r'`/g"

Satır içi düzenleme yapıyordum sed -i '' -e ...ve bir ^Mcaret M (ctrl + m) dosyasına yazılmayla ilgili sorunlar yaşıyordum . Aynı parametreleri kullanarak perl kullandım.
Steve Tauber

2
Lütfen ikinci kodun özel bir yeni satır kodu LF CR (MS-DOS CR LF'nin tersi) eklediğini unutmayın! Hem Unix benzeri işletim sistemleri hem de Mac OS X yalnızca LF ( \n) kullanır.
pabouk

Sed ifademde başka bir şey o kadar mutsuzluğa neden oldu ( echo...ve yeni satır olmadan iyi çalışmasına rağmen) bunu vim'de yaptım.
Ahmed Fasih

1
Veya basitçe: sed "s/regexp/`echo`/g"- Bu, LF-CR yerine tek bir LF üretecektir
mojuba

2
@mojuba: No: boş dize ile`echo` sonuçlanacaktır , çünkü komut ikameleri sürekli olarak tüm son satırları keser. Doğrudan tek bir satırsonu eklemek için bir komut ikamesi kullanmanın bir yolu yoktur (ve eklenmesi - yani ek bir CR - korkunç bir fikirdir). \n\r
mklement0

15
echo one,two,three | sed 's/,/\
/g'

1
+1 mükemmel çalıştı ve oldukça ileri / hatırlaması kolay
gMale

2
Bu cevap aslında bir bash çözümü yerine sed bir çözümdür. Gibi yapılar kullanan her şey yeni satır oluşturmak için kabuk dayanmaktadır. Bu tür çözeltiler taşınabilir olmayabilir. Bu. Tabii ki, aynı zamanda tgamblin'in 2009'daki cevabındaki ikinci örneğin bir kopyası.$'\n'
ghoti

10

Bu durumda sed kullanmıyorum. Tr kullanıyorum.

cat Somefile |tr ',' '\012' 

Bu virgül alır ve onu satır başı ile değiştirir.


1
Bunun da işe yaradığını gördüm: cat Somefile | tr ',' '\n'YMMV
LS

9

Tam perl düzenli ifade desteği (sed ile elde ettiğinizden çok daha güçlü) avantajı ile perl tek katmanlarını sed ile yaptığınız gibi kullanabilirsiniz . * Nix platformları arasında da çok az değişiklik vardır - perl genellikle perl'dir. Böylece, özel sisteminizin sed sürümünü nasıl istediğinizi yapmak konusunda endişelenmeyi bırakabilirsiniz.

Bu durumda,

perl -pe 's/(regex)/\n$1/'

-pe perl'i sed'in normal çalışma moduna benzer şekilde bir "yürüt ve yazdır" döngüsüne yerleştirir.

' diğer her şeyi tırnak içine alır, böylece kabuk karışmaz

()normal ifadeyi çevreleyen bir gruplama operatörüdür. $1ikame sağ tarafında bu parens içinde eşleşen her şeyi yazdırır.

Son olarak, \nyeni bir satır.

Gruplama operatörü olarak parantez kullanıp kullanmadığınıza bakılmaksızın, eşleştirmeye çalıştığınız parantezlerden kaçmanız gerekir. Dolayısıyla, yukarıda listelediğiniz desenle eşleşen bir normal ifade,

\(\d\d\d\)\d\d\d-\d\d\d\d

\(veya \)değişmez bir paren ile \deşleşir ve bir rakamla eşleşir.

Daha iyi:

\(\d{3}\)\d{3}-\d{4}

Parantez içindeki sayıların ne yaptığını anlayabileceğinizi düşünüyorum.

Ayrıca, normal ifadeniz için / dışında ayırıcılar kullanabilirsiniz. Yani eğer eşleştirmeniz gerekiyorsa / kaçmanız gerekmeyecek. Aşağıdakilerden herhangi biri cevabımın başındaki normal ifadeye eşdeğer. Teorik olarak , standartların yerine herhangi bir karakteri koyabilirsiniz .

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

Birkaç son düşünce.

kullanarak -neyerine -pebenzer atmasına karşın otomatik sonunda yazdırmaz. Kendi başınıza yazdırmak istiyorsanız kullanışlı olabilir. Örneğin, işte bir grep-benzeri ( m/foobar/bir normal ifade eşleşmesi):

perl -ne 'if (m/foobar/) {print}'

Yeni satırlarla uğraşmayı zahmetli buluyorsanız ve bunun sizin için sihirli bir şekilde ele alınmasını istiyorsanız, ekleyin -l. Yine de, yeni satırlarla çalışan OP için yararlı değil.

Bonus ipucu - pcre paketi yüklüyse, pcregreptam perl uyumlu regexes kullanan ile birlikte gelir .


4

Hmm, sadece kaçan yeni satırların sed(GNU sed 4.2.1 var),

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar

1
Belirtildiği gibi, bu, GNU sed'in çeşitli sürümleriyle çalışır, ancak macOS'a dahil edilen sed ile çalışmaz.
LS

4
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

El Captitan'da ()destekle iyi çalıştı


Bu harika çalıştı ve hatta kendi amacı için uzmanlaşmak için test etmek ve tahmin etmek için tam bir emir veriyorsunuz. İyi iş!
jxramos

3

Linux'ta akış çıktısına yeni satır eklemek için aşağıdakileri kullandım:

sed -i "s/def/abc\\\ndef/" file1

Neredeydi file1:

def

Sed yerinde değiştirilmeden önce ve:

abc
def

Sed yerine değiştirdikten sonra. Lütfen dikkat edin \\\n. Desenlerin "içinde bir tane varsa, kullanarak kaçın \".


Benim için yukarıdaki kod çalışmıyor. kabuktan parametreye girdiği için LF yerine sedekler . --- Bu kod çalışır: . --- , (CentOS sürüm 6.4 / Ubuntu 12.04.3). \n\\nsed -i "s/def/abc\ndef/" file1GNU sed version 4.2.1GNU bash, version 4.1.2(1) / 4.2.25(1)
pabouk

2

sed'de "\ 1", "\ 2", .... ile deseninizdeki gruplara başvurabilirsiniz. Böylece aradığınız desen "PATTERN" ise ve önüne "ÖNCE" eklemek istiyorsanız , kullanabilirsiniz, kaçan sans

sed 's/(PATTERN)/BEFORE\1/g'

yani

  sed 's/\(PATTERN\)/BEFORE\1/g'

Yeni yaptı: testfile content = "ABC ABC ABC". "Sed 's / \ (ABC \) / \ n \ 1 / g' testfile koştu, yeni satırlar var. Kaçışlarla denemeler yapın, deseninize bir seferde 1 şey eklemeye çalışın, örn. desen, ardından grup eşleşmelerini kontrol, daha sonra yeni satır denetimi ekleyin.
Steve B.

Ben sadece tam olarak denedim ve "nABC nABC nABC 'var. Sed başka bir sürümünü kullanıyor musunuz?
Todd Gamblin

kabuk kaçması muhtemelen tgamblin'in girişimlerini engelliyor. Steve B'nin yaptığı gibi tek tırnak içine tam sed argümanlarını koymak bunu düzeltmelidir. Sed'in farklı sürümleri yeni satır için \ n anlamıyor olabilir.
Dan Pritts

2

Bunu awk ile de yapabilirsiniz. -vDeseni sağlamak için :

awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file

Bu, bir çizginin belirli bir desen içerip içermediğini kontrol eder. Öyleyse, başlangıcına yeni bir satır ekler.

Temel bir örneğe bakın:

$ cat file
hello
this is some pattern and we are going ahead
bye!
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
hello
this is some 
pattern and we are going ahead
bye!

Bir satırdaki tüm desenleri etkileyeceğini unutmayın:

$ cat file
this pattern is some pattern and we are going ahead
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d
this 
pattern is some 
pattern and we are going ahead

1
1 bu konuda ne yapar?
whatahitson

1
@whatahitson 1, Awk'ta kısayol olarak kullanılır {print $0}. Bunun nedeni True olarak değerlendirilen herhangi bir koşulun Awk'un geçerli kaydı yazdırmayı içeren varsayılan eylemini tetiklemesidir.
fedorqui 'SO

1

Bu benim için MAC'de çalışıyor

sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt

Dono onun mükemmel biri olsun ...


1

Bu sorunun tüm cevaplarını okuduktan sonra, yine de aşağıdaki örnek komut dosyasının doğru sözdizimini almam için birçok girişimde bulundum:

#!/bin/bash
# script: add_domain
# using fixed values instead of command line parameters $1, $2
# to show typical variable values in this example
ipaddr="127.0.0.1"
domain="example.com"
# no need to escape $ipaddr and $domain values if we use separate quotes.
sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts

Komut \ndosyası, tek bir sedkomut kullanarak dosyanın sonuna yeni bir satır ve ardından başka bir metin satırı ekler .


1
sed -e 's/regexp/\0\n/g'

\ 0 null, bu nedenle ifadeniz null (hiçbir şey) ile değiştirilir ve sonra ...
\ n yeni satırdır

Unix'in bazı lezzetleri üzerinde işe yaramaz, ancak bence sorununuzun çözümü.

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow

0

Red Hat üzerinde vi, ben sadece \ r karakteri kullanarak satır başı eklemek mümkün. Bu dahili olarak 'sed' yerine 'ex' yürütür inanıyorum, ama benzer ve vi kod yamaları gibi toplu düzenlemeler yapmak için başka bir yol olabilir. Örneğin. Parantez sonra taşıma döner ısrar bir if ifadesi ile bir arama terimi çevreliyorum:

:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/

Ayrıca işleri daha iyi hizalamak için bazı sekmeler eklemek vardı unutmayın.

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.