Bagaimana saya bisa mengedit n baris terakhir dalam file?

10

Apakah ada perintah yang akan memungkinkan saya untuk mengedit baris n terakhir dalam file? Saya memiliki beberapa file, yang semuanya memiliki jumlah baris yang berbeda di dalamnya. Tapi saya ingin memodifikasi n baris terakhir di setiap file. Tujuannya adalah untuk mengganti koma dengan titik koma di n baris terakhir. Tetapi hanya dalam n baris terakhir.

Saya tidak ingin menghapus baris apa pun, saya hanya ingin mengganti setiap koma dengan titik koma di baris n terakhir di setiap file.

Menggunakan perintah sed saya bisa mengganti baris terakhir dengan perintah ini. Seperti yang dijelaskan di sini: Bagaimana saya bisa menghapus teks pada baris terakhir file?

Tapi ini hanya memungkinkan saya untuk memodifikasi baris terakhir, dan bukan jumlah n baris terakhir.

sku2003
sumber
1
Cukup menggunakan di sed '24,$s/,/:/g' filename mana 24garis awalnya`
Valentin Bajrami

Jawaban:

13

Untuk mengganti koma dengan titik koma pada n baris terakhir dengan ed:

n=3
ed -s input <<< '$-'$((n-1))$',$s/,/;/g\nwq'

Pisahkan itu:

  • ed -s = jalankan ed secara diam-diam (jangan melaporkan byte yang ditulis di akhir)
  • '$-'= dari akhir file ( $) minus ...
  • $((n-1)) = n-1 baris ...
  • ( $' ... '= kutip sisa perintah untuk melindunginya dari shell)
  • ,$s/,/;/g= ... sampai akhir file ( ,$), cari dan ganti semua koma dengan titik koma.
  • \nwq = akhiri perintah sebelumnya, lalu simpan dan keluar

Untuk mengganti koma dengan titik koma pada n baris terakhir dengan sed:

n=3
sed -i "$(( $(wc -l < input) - n + 1)),\$s/,/;/g" input

Pisahkan itu:

  • -i = edit file "di tempat"
  • $(( ... )) = lakukan beberapa matematika:
  • $( wc -l < input) = dapatkan jumlah baris dalam file
  • -n + 1 = mundur n-1 baris
  • ,\$ = dari n-1 baris hingga akhir file:
  • s/,/;/g = ganti koma dengan titik koma.
Jeff Schaller
sumber
Bisa ganti wc -l < inputdengan wc -l input. Seharusnya lebih cepat beberapa nanodetik :)
gardenhead
1
kecuali yang wc -l inputmenghasilkan nama file juga; kami hanya ingin penghitungan baris
Jeff Schaller
Saran pertama dengan ed baik dan sederhana.
sku2003
Saya akhirnya mendapatkan bantuan dari sisi yang sama sekali berbeda. Ini menghasilkan potongan kode yang aneh, yang berfungsi tetapi panjang dan aneh. Saya kira ini adalah beberapa hal aneh yang bisa Anda dapatkan ketika harus mengumpulkan solusi. Bagaimanapun, milik Anda lebih cantik, lebih pendek, dan tidak lebih rumit dari milik saya: Kode di sini juga berfungsi:
sku2003
cat input.file | sed 's /, /, \ n / g' | sed -n '1! G; h; $ p' | awk -vn = 2 'NR <= n {gsub (",", ";", $ 0)} {print}' | sed -n '1! G; h; $ p' | sed '/ ^ \ s * $ / d'> output.file
sku2003
6

Solusi menggunakan tac dan sed untuk mengganti setiap koma dengan titik koma di 50 baris terakhir file.txt:

tac file.txt | sed '1,50s/,/;/g' | tac
Gohu
sumber
5

Dengan GNU headdan shell seperti Bourne:

n=20
{ head -n -"$n"; tr , ';'; } < file 1<> file

Kami menimpa file itu sendiri. Tidak masalah di sini untuk transliterasi byte-ke-byte tetapi tidak perlu jika modifikasi menyiratkan mengubah ukuran file (dalam hal ini, Anda ingin mengganti 1<> filedengan > other-file && mv other-file filemisalnya).

Stéphane Chazelas
sumber
1
Ini dokumen untuk1<> , yang belum saya kenal. Selain itu, spongedari moreutils adalah alat yang bagus untuk saluran pipa tempat Anda ingin menimpa input Anda.
Miles
1

Mari kita asumsikan kita ingin mengganti 7baris terakhir dari urutan berikut dengan skrip shell dan implementasi GNU dari sed:

$ seq 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Langkah 1 : mari kita dapatkan nomor baris urutan terakhir seperti berikut. Lihatlah ini dan itu :

$ lastLine=`seq 20|sed -n '$='`

$ echo $lastLine 
20

Langkah 2 : mari kita tentukan jumlah baris (di akhir urutan) yang ingin kita edit:

$ numberOfLines=7

$ echo $numberOfLines 
7

Langkah 3 : mari kita hitung garis start berdasarkan variabel sebelumnya, seperti berikut ini. Lihatlah ini :

$ startLine=`expr $lastLine - $numberOfLines + 1`

$ echo $startLine 
14

Langkah 4 : Sekarang, kita dapat mengganti 7 baris terakhir dari urutan dengan yang lain, seperti berikut ini. Lihatlah ini :

$ seq 20|sed -e "$startLine,+$numberOfLines{s/[12]/WoW/}"
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0

Langkah 4 menggunakan bagian 4.4 dari halaman manual sed yang mengatakan:

'ADDR1,+N'
     Matches ADDR1 and the N lines following ADDR1.

Langkah 4, juga menggunakan tanda kutip ganda seperti yang disebutkan di sini .


Nah, 4 langkah itu tidak perlu jika kita menggunakan jawaban Gohu seperti ini:

$ seq 20 |tac|sed -e '1,7{s/[12]/WoW/}'|tac
1
2
3
4
5
6
7
8
9
10
11
12
13
WoW4
WoW5
WoW6
WoW7
WoW8
WoW9
WoW0
pengguna3405291
sumber
0

Gunakan taildan pipa untuk sed:

tail -n 20 file | sed 's/,/;/g'

Ini berfungsi pada file selama 20 baris terakhir. Jika Anda ingin agar Anda dapat mengarahkan langsung ke file gunakan:

tail -n 20 file | sed -i 's/,/;/g'

John Goofy
sumber