日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Go實現替換(覆蓋)文件某一行內容的示例代碼_Golang

作者:xiaoyaoyou.xyz ? 更新時間: 2022-09-03 編程語言

1、前言

有這樣一個需求,我們查找到文件中帶有某個關鍵詞的一行內容后,對該行內容進行替換,替換成我們需要的新內容,比如修改網絡配置文件、修改圖片地址、修改代碼中所有關鍵詞等,類似于編輯器中的關鍵詞替換功能,只不過我們是直接判斷文件而已。

2、實現覆蓋某一行文件內容的思路

1、打開文件
2、讀取文件每一行
3、根據關鍵詞判斷是否是需要覆蓋的行,是的話則從行開頭寫內容,使其覆蓋該行舊內容
由于是覆蓋,所以我們有一個前提是新寫入的內容長度需要大于等于舊內容的長度,至于新內容小于舊內容的情況下,我們在擴展中再做嘗試,基本思路包括兩個:1、寫入空內容覆蓋多出的位置(應該不行,可以試一下);2、新內容寫入后直接加入換行,然后將之前文件剩余內容覆蓋多出來的這部分,還是覆蓋的思想。

3、實現覆蓋某一行內容的代碼示例

我們這里以修改我的虛擬機中的網絡配置文件為例做一個簡單的示例(記得先備份):

原本的Ubuntu配置文件內容:

$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto ens33
iface ens33 inet static
address 40.40.40.210
gateway 40.40.40.1
netmask 255.255.255.0

然后我們通過address、gateway、netmask等關鍵詞來修改最后三行的內容,以此來修改配置文件中的ip地址、網關和子網掩碼。

代碼內容:

package main

import (
?? ?"bufio"
?? ?"fmt"
?? ?"io"
?? ?"os"
?? ?"strings"
)

func main() {
? ? //讀寫方式打開文件
?? ?file, err := os.OpenFile("/etc/network/interfaces", os.O_RDWR, 0666)
?? ?if err != nil {
?? ??? ?fmt.Println("open file filed.", err)
?? ??? ?return
?? ?}
? ? //defer關閉文件
?? ?defer file.Close()

? ? //獲取文件大小
?? ?stat, err := file.Stat()
?? ?if err != nil {
?? ??? ?panic(err)
?? ?}
?? ?var size = stat.Size()
?? ?fmt.Println("file size:", size)

? ? //讀取文件內容到io中
?? ?reader := bufio.NewReader(file)
?? ?pos := int64(0)
?? ?ip := "40.40.40.220"
?? ?gateway := "40.40.40.1"
?? ?netmask := "255.255.255.0"
?? ?for {
? ? ? ? //讀取每一行內容
?? ??? ?line, err := reader.ReadString('\n')
?? ??? ?if err != nil {
? ? ? ? ? ? //讀到末尾
?? ??? ??? ?if err == io.EOF {
?? ??? ??? ??? ?fmt.Println("File read ok!")
?? ??? ??? ??? ?break
?? ??? ??? ?} else {
?? ??? ??? ??? ?fmt.Println("Read file error!", err)
?? ??? ??? ??? ?return
?? ??? ??? ?}
?? ??? ?}
?? ??? ?fmt.Println(line)

? ? ? ? //根據關鍵詞覆蓋當前行
?? ??? ?if strings.Contains(line, "address") {
?? ??? ??? ?bytes := []byte("address " + ip + "\n")
?? ??? ??? ?file.WriteAt(bytes, pos)
?? ??? ?} else if strings.Contains(line, "gateway") {
?? ??? ??? ?bytes := []byte("gateway " + gateway + "\n")
?? ??? ??? ?file.WriteAt(bytes, pos)
?? ??? ?} else if strings.Contains(line, "netmask") {
?? ??? ??? ?bytes := []byte("netmask " + netmask + "\n")
?? ??? ??? ?file.WriteAt(bytes, pos)
?? ??? ?}

? ? ? ? //每一行讀取完后記錄位置
?? ??? ?pos += int64(len(line))
?? ?}
}

結果:

$ sudo ./go_build_test_go_linux?
[sudo] xx 的密碼:?
file size: 180
# interfaces(5) file used by ifup(8) and ifdown(8)

auto lo

iface lo inet loopback

auto ens33

iface ens33 inet static

address 40.40.40.210

gateway 40.40.40.1

netmask 255.255.255.0

File read ok!
$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto ens33
iface ens33 inet static
address 40.40.40.220
gateway 40.40.40.1
netmask 255.255.255.0

關鍵點:每讀取一行記錄目前的移動位置,然后調用file.WriteAt進行內容覆蓋寫入(不能是追加方式),因為找到這一行的時候記錄的位置正好是上一行的末尾,所以正好覆蓋。

4、擴展

其實最方便的方式其實是shell腳本的方式,然后通過各種語言都可以調用,并且某些時候也可以單獨執行腳本。

其次,對于新內容長度少于舊內容的長度時無法做到全部覆蓋,這個時候就稍微麻煩一點,再下下一行的時候或者其余的內容全部讀取然后覆蓋寫入即可。

不明白接口使用的查看一下官方的io包,后面我們也會再專注整理一下io標準庫的接口。

原文鏈接:https://blog.csdn.net/weixin_39510813/article/details/115675198

欄目分類
最近更新