Masukkan garis pada nomor garis tertentu dengan sed atau awk


146

Saya memiliki file skrip yang perlu saya modifikasi dengan skrip lain untuk memasukkan teks pada baris ke-8.

String untuk memasukkan:, Project_Name=sowstestke dalam file bernama start.

Saya mencoba menggunakan awk dan sed, tetapi perintah saya semakin kacau.

Jawaban:


231
sed -i '8i8 This is Line 8' FILE

sisipan di baris 8

8 This is Line 8

ke dalam file FILE

-i melakukan modifikasi langsung ke file FILE, tidak ada output ke stdout, seperti yang disebutkan dalam komentar oleh glenn jackman.


3
Ya, -i switch khusus untuk GNU-sed.
pengguna tidak diketahui

1
Tidak. -I berarti "memodifikasi file yang ditentukan di tempat". Sisipkan vs tambahkan dicapai dengan '8sesuatu' vs '8sesuatu', independen dari -i-switch.
pengguna tidak diketahui

11
pengguna mac: dengan homebrew, brew install gnu-seddan kemudian gunakan ini dengangsed
cwd

4
Ini sangat berguna! Apakah ada cara bagi saya untuk memasukkan spasi di awal baris? Saya perhatikan sed tidak memperhatikan spasi putih awal ...
elju

9
@elju: Ya, menutupinya dengan garis miring terbalik: sed '8i\ 8 This is Line 8' FILE.
pengguna tidak dikenal


19

OS X / macOS / FreeBSD sed

The -ibendera bekerja secara berbeda pada MacOS seddaripada di GNU sed.

Inilah cara menggunakannya di macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Lihat man 1 seduntuk info lebih lanjut.


18

jawaban awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@glenn jackman saya harus masuk #define SERVER@"http://10.35.42.54/ms0.8"ke jalur tertentu. Bagaimana saya bisa mencapai ini?
Nevin Raj Victor

1
Saya pikir Nevin hanya perlu melepaskan diri dari tanda kutip di string-nya dengan garis miring terbalik
Chris Koknat

@waLLe, mulailah dengan halaman info awk yang memiliki deskripsi yang bagus tentang bagaimana awk bekerja. Di sini, saya memiliki 2 pasangan "kondisi {aksi}", yang ke-2 tidak memiliki kondisi yang berarti tindakan dilakukan untuk setiap catatan. Setelah Anda selesai membaca dan masih memiliki pertanyaan, beri tahu saya.
glenn jackman

@glennjackman hampir di sana .. hanya tidak mendapatkan ini: file> file.new
w411 3

"file" mewakili nama file yang sedang dikerjakan awk. >adalah simbol pengalihan shell sehingga output awk disimpan dalam file bernama "file.new".
glenn jackman

16

POSIX sed(dan misalnya OS X's sed, di sedbawah) perlu idiikuti oleh garis miring terbalik dan baris baru. Setidaknya OS X sedtidak menyertakan baris baru setelah teks yang dimasukkan:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Untuk mengganti garis, Anda dapat menggunakan perintah c(ubah) atau s(ganti) dengan alamat numerik:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Alternatif menggunakan awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkmenafsirkan garis miring terbalik dalam variabel yang diteruskan dengan -vtetapi tidak dalam variabel yang diteruskan menggunakan ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Keduanya ENVIRONdan -vdidefinisikan oleh POSIX.


7

Solusi Perl:

cepat dan kotor:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l menghapus baris baru dan menambahkannya kembali, menghilangkan kebutuhan untuk "\ n"
  • -p loop di atas file input, mencetak setiap baris
  • -e mengeksekusi kode dalam tanda kutip tunggal

$. adalah nomor baris

setara dengan solusi awk @ glenn, menggunakan argumen bernama:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s memungkinkan parser argumen yang belum sempurna
  • -- mencegah -n dan -s diurai oleh parser argumen perl standar

argumen perintah posisi:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

variabel lingkungan:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV adalah hash yang berisi semua variabel lingkungan

Getopt to parse argumen ke hash% o:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Nama opsi yang panjang dan lebih panjang

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt adalah solusi perpustakaan standar yang direkomendasikan.
Ini mungkin berlebihan untuk skrip perl satu baris, tetapi dapat dilakukan


2
Kudos kepada Anda, Chris, karena telah meluangkan waktu untuk menjelaskan semua itu dan mengungkapkannya dengan sangat baik, tetapi wow inilah mengapa saya tidak suka perl.
rsaw

5

Bagi mereka yang menggunakan SunOS yang bukan GNU, kode berikut akan membantu:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J dimasukkan dengan ^ V + ^ J
  • Tambahkan baris baru setelah '1i.
  • \ HARUS menjadi karakter terakhir dari baris.
  • Bagian kedua dari perintah harus di baris kedua.

5

sed -e '8iProject_Name=sowstest' -i start menggunakan sed GNU

Contoh dijalankan:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 

Dari mana asal jejak $pada jalur 3 setelah penyisipan?
jww

Ini dari -Abendera ke cat:)
jno

bagaimana jika string yang ingin Anda masukkan mengandung tanda kutip, tanda kurung dll?
Anentropic

Lihat pembaruan pada teks di atas. Itu berarti, Anda harus melarikan diri dari karakter itu sebagaimana mestinya.
jno

0

sed -i "" -e $ '4 a \\ n''Project_Name = sowstest' mulai

  • Baris ini berfungsi dengan baik di macOS
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.