Bagaimana cara menyisipkan baris baru sebelum pola dalam satu baris?
Misalnya, ini akan menyisipkan baris baru di belakang pola regex.
sed 's/regex/&\n/g'
Bagaimana saya bisa melakukan hal yang sama tetapi di depan polanya?
Dengan contoh file masukan ini, pola yang akan dicocokkan adalah nomor telepon.
some text (012)345-6789
Harus menjadi
some text
(012)345-6789
sed '/regex/G'
Jawaban:
Ini berfungsi di
bash
danzsh
, diuji di Linux dan OS X:sed 's/regexp/\'$'\n/g'
Secara umum, for
$
diikuti oleh string literal dalam tanda kutip tunggalbash
melakukan substitusi backslash gaya C, misalnya$'\t'
diterjemahkan ke tab literal. Plus, sed ingin literal baris baru Anda di-escape dengan garis miring terbalik, maka\
sebelumnya$
. Dan akhirnya, tanda dolar itu sendiri tidak boleh dikutip sehingga ditafsirkan oleh shell, oleh karena itu kita menutup kutipan sebelum$
dan kemudian membukanya lagi.Sunting : Seperti yang disarankan dalam komentar oleh @ mklement0, ini juga berfungsi:
sed $'s/regexp/\\\n/g'
Apa yang terjadi di sini adalah: seluruh perintah sed sekarang menjadi string gaya-C, yang berarti garis miring terbalik yang dibutuhkan sed untuk ditempatkan sebelum literal baris baru sekarang harus di-escape dengan garis miring terbalik lain. Meskipun lebih mudah dibaca, dalam hal ini Anda tidak akan dapat melakukan substitusi string shell (tanpa membuatnya jelek lagi.)
sumber
sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'
. Perhatikan dua tanda kutip tunggal setelah \ n. Yang pertama menutup bagian "$
" sehingga sisa baris tidak terpengaruh olehnya. Tanpa tanda kutip tersebut, \ 2 diabaikan.sed $'s/regexp/\\\n/g'
, yang meningkatkan keterbacaan - satu-satunya pengecualian adalah bahwa Anda kemudian harus menggandakan semua literal\
karakter.Beberapa jawaban lain tidak berfungsi untuk versi sed. Mengganti posisi
&
dan\n
berhasil.sed 's/regexp/\n&/g'
Sunting: Ini sepertinya tidak berfungsi di OS X, kecuali Anda menginstal
gnu-sed
.sumber
brew install gnu-sed
diikuti olehgsed 's/regexp/\n&/g'
echo 'alias sed=gsed' >> ~/.bashrc
Sed, Anda tidak dapat menambahkan baris baru dalam arus keluaran dengan mudah. Anda perlu menggunakan garis lanjutan, yang canggung, tetapi berhasil:
$ sed 's/regexp/\ &/'
Contoh:
$ echo foo | sed 's/.*/\ &/' foo
Lihat di sini untuk detailnya. Jika Anda menginginkan sesuatu yang tidak terlalu canggung, Anda dapat mencoba menggunakan
perl -pe
dengan grup pencocokan alih-alih sed:$ echo foo | perl -pe 's/(.*)/\n$1/' foo
$1
merujuk ke grup pertama yang cocok dalam ekspresi reguler, dengan grup di dalam tanda kurung.sumber
perl -pi -e 's/(.*)/\n$1/' foo
s
pemanggilan fungsi (tidak seperti implementasi GNU Sed, yang mendukung ) . Jawaban di atas berfungsi dengan kedua implementasi; untuk gambaran umum tentang semua perbedaan, lihat di sini .Di mac saya, berikut ini menyisipkan satu 'n' alih-alih baris baru:
sed 's/regexp/\n&/g'
Ini menggantikan dengan baris baru:
sed "s/regexp/\\`echo -e '\n\r'`/g"
sumber
sed -i '' -e ...
dan mengalami masalah dengan^M
tanda sisipan M (ctrl + m) yang ditulis ke file. Saya akhirnya menggunakan perl dengan parameter yang sama.\n
).echo...
dan baris baru) sehingga saya hanya melakukan ini di vim.sed "s/regexp/`echo`/g"
- ini akan menghasilkan satu LF, bukan LF-CR`echo`
akan menghasilkan string kosong , karena penggantian perintah selalu memotong semua baris baru yang tertinggal. Tidak ada cara untuk menggunakan substitusi perintah untuk langsung memasukkan satu baris baru (dan menyisipkan\n\r
- misalnya, CR tambahan - adalah ide yang buruk).echo one,two,three | sed 's/,/\ /g'
sumber
$'\n'
mengandalkan shell untuk menghasilkan baris baru. Solusi tersebut mungkin tidak portabel. Yang ini. Tentu saja, ini juga duplikat dari contoh kedua dalam jawaban tgamblin dari tahun 2009.Dalam hal ini, saya tidak menggunakan sed. Saya menggunakan tr.
cat Somefile |tr ',' '\012'
Ini mengambil koma dan menggantinya dengan kembali kereta.
sumber
cat Somefile | tr ',' '\n'
YMMVAnda dapat menggunakan perl satu baris seperti yang Anda lakukan dengan sed, dengan keuntungan ekspresi reguler perl penuh dukungan (yang jauh lebih kuat daripada yang Anda dapatkan dengan sed). Ada juga variasi yang sangat sedikit di seluruh platform * nix - perl umumnya adalah perl. Jadi Anda bisa berhenti mencemaskan tentang bagaimana membuat versi sistem Anda sed melakukan apa yang Anda inginkan.
Dalam hal ini, Anda bisa melakukannya
perl -pe 's/(regex)/\n$1/'
-pe
menempatkan perl ke dalam loop "eksekusi dan cetak", seperti mode operasi normal sed.'
mengutip yang lainnya sehingga shell tidak akan mengganggu()
mengelilingi regex adalah operator pengelompokan.$1
di sisi kanan substitusi mencetak apa pun yang cocok di dalam tanda kurung ini.Akhirnya,
\n
adalah baris baru.Terlepas dari apakah Anda menggunakan tanda kurung sebagai operator pengelompokan, Anda harus keluar dari tanda kurung yang ingin Anda cocokkan. Jadi ekspresi reguler untuk mencocokkan pola yang Anda cantumkan di atas akan menjadi seperti ini
\(
atau\)
cocok dengan tanda kurung literal, dan\d
cocok dengan digit.Lebih baik:
Saya membayangkan Anda bisa mengetahui apa yang dilakukan angka-angka di kawat gigi.
Selain itu, Anda dapat menggunakan pembatas selain / untuk ekspresi reguler Anda. Jadi jika Anda perlu mencocokkan / Anda tidak perlu menghindarinya. Salah satu dari berikut ini setara dengan ekspresi reguler di awal jawaban saya. Secara teori, Anda dapat mengganti karakter apa pun untuk standar /.
perl -pe 's#(regex)#\n$1#' perl -pe 's{(regex)}{\n$1}'
Beberapa pemikiran terakhir.
menggunakan
-ne
alih-alih melakukan-pe
tindakan serupa, tetapi tidak secara otomatis mencetak di akhir. Ini bisa berguna jika Anda ingin mencetak sendiri. Misalnya, ini grep-alike (m/foobar/
adalah pertandingan regex):perl -ne 'if (m/foobar/) {print}'
Jika Anda merasa berurusan dengan baris baru merepotkan, dan Anda ingin menangani hal itu secara ajaib, tambahkan
-l
. Tidak berguna untuk OP, yang bekerja dengan baris baru.Tip bonus - jika Anda memiliki paket pcre yang terinstal, itu disertakan
pcregrep
, yang menggunakan regex lengkap yang kompatibel dengan perl.sumber
Hmm, baris baru yang lolos begitu saja tampaknya berfungsi di versi yang lebih baru
sed
(Saya memiliki GNU sed 4.2.1),dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;' foo bar
sumber
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'
bekerja dengan baik di El Captitan dengan
()
dukungansumber
Untuk memasukkan baris baru ke aliran keluaran di Linux, saya menggunakan:
sed -i "s/def/abc\\\ndef/" file1
Dimana
file1
:Sebelum penggantian sed di tempat, dan:
Setelah sed di tempat penggantian. Harap perhatikan penggunaan
\\\n
. Jika polanya memiliki bagian"
dalam, hindari menggunakan\"
.sumber
sed
menyisipkan\n
alih-alih LF karena mendapat\\n
parameter dari shell. --- Kode ini bekerja:sed -i "s/def/abc\ndef/" file1
. ---GNU sed version 4.2.1
,GNU bash, version 4.1.2(1) / 4.2.25(1)
(CentOS rilis 6.4 / Ubuntu 12.04.3).sed Anda dapat mereferensikan grup dalam pola Anda dengan "\ 1", "\ 2", .... jadi jika pola yang Anda cari adalah "POLA", dan Anda ingin memasukkan "SEBELUMNYA" di depannya , Anda dapat menggunakan, tanpa melarikan diri
sed 's/(PATTERN)/BEFORE\1/g'
yaitu
sed 's/\(PATTERN\)/BEFORE\1/g'
sumber
Anda juga dapat melakukan ini dengan awk, menggunakan
-v
untuk memberikan pola:awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file
Ini memeriksa apakah garis berisi pola tertentu. Jika demikian, itu menambahkan baris baru ke awalnya.
Lihat contoh dasar:
$ 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!
Perhatikan itu akan mempengaruhi semua pola dalam satu baris:
$ 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
sumber
1
digunakan di Awk sebagai singkatan dari{print $0}
. Alasannya adalah bahwa kondisi apa pun yang mengevaluasi ke True memicu tindakan default AWK, yang terdiri dari pencetakan rekaman saat ini.Ini bekerja di MAC untuk saya
sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt
Dono apakah itu sempurna ...
sumber
Setelah membaca semua jawaban atas pertanyaan ini, saya masih perlu banyak upaya untuk mendapatkan sintaks yang benar ke skrip contoh berikut:
#!/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
Skrip menambahkan baris baru
\n
diikuti dengan baris teks lain ke akhir file menggunakan satused
perintah.sumber
sed -e 's/regexp/\0\n/g'
\ 0 adalah nol, jadi ekspresi Anda diganti dengan nol (tidak ada) dan kemudian ...
\ n adalah baris baru
Pada beberapa rasa Unix tidak berfungsi, tetapi saya pikir itu adalah solusi untuk masalah Anda.
echo "Hello" | sed -e 's/Hello/\0\ntmow/g' Hello tmow
sumber
Di vi di Red Hat, saya bisa memasukkan carriage return hanya dengan menggunakan karakter \ r. Saya percaya ini secara internal mengeksekusi 'ex' daripada 'sed', tetapi serupa, dan vi bisa menjadi cara lain untuk melakukan pengeditan massal seperti tambalan kode. Sebagai contoh. Saya mengelilingi istilah pencarian dengan pernyataan if yang bersikeras bahwa kereta kembali setelah kurung kurawal:
:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/
Perhatikan bahwa saya juga menyuruhnya memasukkan beberapa tab untuk membuat semuanya selaras lebih baik.
sumber
Dalam kasus saya, metode di bawah ini berfungsi.
sed -i 's/playstation/PS4/' input.txt
Dapat ditulis sebagai:
sed -i 's/playstation/PS4\nplaystation/' input.txt
Playstation PS4
Pertimbangkan untuk menggunakan \\ n saat menggunakannya dalam string literal.
sed : adalah editor aliran
-i : Memungkinkan untuk mengedit file sumber
+ : Apakah pembatas.
Saya harap informasi di atas berfungsi untuk Anda 😃.
sumber