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.