Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼
1、
有這樣一個(gè)需求,我們查找到文件中帶有某個(gè)關(guān)鍵詞的一行內(nèi)容后,對該行內(nèi)容進(jìn)行替換,替換成我們需要的新內(nèi)容,比如修改網(wǎng)絡(luò)配置文件、修改圖片地址、修改代碼中所有關(guān)鍵詞等,類似于編輯器中的關(guān)鍵詞替換功能,只不過我們是直接判斷文件而已。
2、實(shí)現(xiàn)覆蓋某一行文件內(nèi)容的思路
1、打開文件
2、讀取文件每一行
3、根據(jù)關(guān)鍵詞判斷是否是需要覆蓋的行,是的話則從行開頭寫內(nèi)容,使其覆蓋該行舊內(nèi)容
由于是覆蓋,所以我們有一個(gè)前提是新寫入的內(nèi)容長度需要大于等于舊內(nèi)容的長度,至于新內(nèi)容小于舊內(nèi)容的情況下,我們在擴(kuò)展中再做嘗試,基本思路包括兩個(gè):1、寫入空內(nèi)容覆蓋多出的位置(應(yīng)該不行,可以試一下);2、新內(nèi)容寫入后直接加入換行,然后將之前文件剩余內(nèi)容覆蓋多出來的這部分,還是覆蓋的思想。
3、實(shí)現(xiàn)覆蓋某一行內(nèi)容的代碼示例
我們這里以修改我的虛擬機(jī)中的網(wǎng)絡(luò)配置文件為例做一個(gè)簡單的示例(記得先備份):
原本的Ubuntu配置文件內(nèi)容:
$ 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等關(guān)鍵詞來修改最后三行的內(nèi)容,以此來修改配置文件中的ip地址、網(wǎng)關(guān)和子網(wǎng)掩碼。
代碼內(nèi)容:
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關(guān)閉文件 ?? ?defer file.Close() ? ? //獲取文件大小 ?? ?stat, err := file.Stat() ?? ?if err != nil { ?? ??? ?panic(err) ?? ?} ?? ?var size = stat.Size() ?? ?fmt.Println("file size:", size) ? ? //讀取文件內(nèi)容到io中 ?? ?reader := bufio.NewReader(file) ?? ?pos := int64(0) ?? ?ip := "40.40.40.220" ?? ?gateway := "40.40.40.1" ?? ?netmask := "255.255.255.0" ?? ?for { ? ? ? ? //讀取每一行內(nèi)容 ?? ??? ?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) ? ? ? ? //根據(jù)關(guān)鍵詞覆蓋當(dāng)前行 ?? ??? ?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)) ?? ?} }
結(jié)果:
$ 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 loopbackauto ens33
iface ens33 inet static
address 40.40.40.220
gateway 40.40.40.1
netmask 255.255.255.0
關(guān)鍵點(diǎn):每讀取一行記錄目前的移動位置,然后調(diào)用file.WriteAt進(jìn)行內(nèi)容覆蓋寫入(不能是追加方式),因?yàn)檎业竭@一行的時(shí)候記錄的位置正好是上一行的末尾,所以正好覆蓋。
4、擴(kuò)展
其實(shí)最方便的方式其實(shí)是shell腳本的方式,然后通過各種語言都可以調(diào)用,并且某些時(shí)候也可以單獨(dú)執(zhí)行腳本。
其次,對于新內(nèi)容長度少于舊內(nèi)容的長度時(shí)無法做到全部覆蓋,這個(gè)時(shí)候就稍微麻煩一點(diǎn),再下下一行的時(shí)候或者其余的內(nèi)容全部讀取然后覆蓋寫入即可。
不明白接口使用的查看一下官方的io包,后面我們也會再專注整理一下io標(biāo)準(zhǔn)庫的接口。
到此這篇關(guān)于Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼的文章就介紹到這了,更多相關(guān)Go 替換文件某一行內(nèi)容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!
版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場,如有內(nèi)容涉嫌侵權(quán),請聯(lián)系alex-e#qq.com處理。