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.

ashok
sumber

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.

Pengguna tidak diketahui
sumber
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
32

Sebuah edjawaban

ed file << END
8i
Project_Name=sowstest
.
w
q
END

.pada jalurnya sendiri berakhir mode input; wmenulis; qseri. GNU ed memiliki wqperintah untuk menyimpan dan keluar, tetapi ed lama tidak.

Bacaan lebih lanjut: https://gnu.org/software/ed/manual/ed_manual.html

glenn jackman
sumber
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.

Mateusz Piotrowski
sumber
18

jawaban awk

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new
glenn jackman
sumber
@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.

Lri
sumber
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

Chris Koknat
sumber
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.
Nasri Najib
sumber
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 ~]# 
jno
sumber
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
Elza James
sumber