Golang中使用sed的技巧与实践
Golang中使用sed的技巧与实践 你好,我有一段Linux bash shell代码:
sed -i -e "s/DRUMCLASS/False/g" "/usr/share/OCTAVA/Rich/HTTP/CLASS" &> /dev/null
如何在Go语言中实现它?我在谷歌上搜索过,但没有找到任何相关的结果。
更多关于Golang中使用sed的技巧与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
正如我所说,我认为不应该从Go中调用sed,而应该在Go内部完成替换工作。
我不太明白,先生 😑 您说的用 ` 包裹代码是什么意思?
也许可以使用 strings.ReplaceAll(...)?
func main() {
fmt.Println("hello world")
}
顺便问一下,@NobbZ 在 Go 语言中应该如何实现 sed 的功能?我上面的代码正确吗?
如何使用 strings.ReplaceAll() 替换文件中的字符串?我认为通过 ReplaceAll 无法实现。 我希望实现与 sed 相同的方式,并且必须快速。
这正是我写 exec.Cmd 时所做的。
它使代码更易于阅读,并且可以防止软件错误地处理你的引号。
对于构成多行代码的代码块,你可以使用三个反引号:
// Your multiline code
func main() {}
使用 os/exec 库中的 exec.Command(“bash”, “-c”, sed -i -e "s/DRUMCLASS/False/g" "/usr/share/OCTAVA/Rich/HTTP/CLASS" &> /dev/null)。
func main() {
fmt.Println("hello world")
}
我已经完成了这个功能,并且它运行正常:
func sed(old string, new string, file string) {
filePath := file
fileData, _ := ioutil.ReadFile(filePath)
fileString := string(fileData)
fileString = strings.ReplaceAll(fileString, old, new)
fileData = []byte(fileString)
_ = ioutil.WriteFile(filePath, fileData, 0o600)
}
- 修复论坛“美化工具”为你引入的错误。引号是错误的。你们俩都可以通过用反引号包裹代码来避免这个问题:
` - 请不要使用那种结构。如果你想用 Go 来做,那就用 Go 的方式来做。如果你到处都使用
exec.Cmd,那你完全可以在 bash 里做。你执行的每一个exec.Cmd都很容易被追踪和恢复。
嗯…我不知道有没有单行的解决方案 也许可以像这样
filePath := "/path/to/somewhere"
fileData, _ := ioutil.ReadFile(filePath)
fileString := string(fileData)
fileString = strings.ReplaceAll(fileString, "old", "new")
fileData = []byte(fileString)
_ = ioutil.WriteFile(filePath, fileData, 0o600)
这应该可行,但我不确定它是否快速/安全/可行
出现错误
command-line-arguments
./5test.go:5:18: 无效的标识符字符 U+201C ‘“’ ./5test.go:5:25: 无效的标识符字符 U+201D ‘”’ ./5test.go:5:30: 无效的标识符字符 U+201C ‘“’ ./5test.go:5:35: 无效的标识符字符 U+201D ‘”’ ./5test.go:5:131: 语法错误:意外的换行符,期望逗号或 )
- 你不需要执行
filePath := file - 你需要检查错误 因此,代码应该像这样:
func sed(old, new, filePath string) error {
fileData, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
fileString := string(fileData)
fileString = strings.ReplaceAll(fileString, old, new)
fileData = []byte(fileString)
err = ioutil.WriteFile(filePath, fileData, 0o600)
if err != nil {
return err
}
return nil
}
当我说“用反引号包裹代码”时,我指的是在论坛发帖时这样做,就像你上一篇帖子那样。
要修正出错的代码,只需将语义引号 “” 替换为用于字符串的语法引号 ""。
这没什么特别的,在论坛中你将会遇到类似这样的轻微语法问题,你需要自己学会处理这些简单的问题。
不过再次强调,除非必要,否则不要使用 exec.Cmd。在 Go 中,你可以完成 sed 能做的所有事情。
如果你只是不停地链式调用 exec.Cmd,那还不如坚持使用一个简单的 bash 脚本,它的体积会小得多,更容易调试,甚至速度更快!
由于我的英语水平有限,我无法理解 :neutral_face: 实际上您是以另一种方式在说。
exec.Command(“bash”, “-c”, `sed -i -e “s/DRUMCLASS/False/g” “/usr/share/OCTAVA/Rich/HTTP/CLASS” &> /dev/null)`
您能纠正这个吗?
实际上我不明白您在说什么,首先您说在代码中加上反引号,我不确定“加上反引号”是什么意思,我以为您是说在 ) 前面加上反引号,所以我才问您。
兄弟,如果您知道他写的是什么,您能纠正它并用多行代码告诉我吗?就像这样:
exec.Command(“bash”, “-c”, `sed -i -e “s/DRUMCLASS/False/g” “/usr/share/OCTAVA/Rich/HTTP/CLASS” &> /dev/null)`
在Go语言中实现类似sed的文本替换功能,可以使用标准库的io/ioutil(Go 1.16+推荐使用os和io包)和strings包。以下是几种实现方式:
方法1:直接文件读取替换(推荐)
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
filePath := "/usr/share/OCTAVA/Rich/HTTP/CLASS"
// 读取文件内容
content, err := ioutil.ReadFile(filePath)
if err != nil {
log.Fatal(err)
}
// 执行替换操作
newContent := strings.ReplaceAll(string(content), "DRUMCLASS", "False")
// 写回文件
err = ioutil.WriteFile(filePath, []byte(newContent), 0644)
if err != nil {
log.Fatal(err)
}
}
方法2:使用正则表达式替换
如果需要更复杂的模式匹配,可以使用regexp包:
package main
import (
"io/ioutil"
"log"
"regexp"
)
func main() {
filePath := "/usr/share/OCTAVA/Rich/HTTP/CLASS"
content, err := ioutil.ReadFile(filePath)
if err != nil {
log.Fatal(err)
}
// 编译正则表达式
re := regexp.MustCompile(`DRUMCLASS`)
// 执行替换
newContent := re.ReplaceAllString(string(content), "False")
err = ioutil.WriteFile(filePath, []byte(newContent), 0644)
if err != nil {
log.Fatal(err)
}
}
方法3:处理大文件的流式替换
对于大文件,可以使用缓冲读写:
package main
import (
"bufio"
"io"
"log"
"os"
"strings"
)
func main() {
filePath := "/usr/share/OCTAVA/Rich/HTTP/CLASS"
tmpPath := filePath + ".tmp"
// 打开源文件
srcFile, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer srcFile.Close()
// 创建临时文件
tmpFile, err := os.Create(tmpPath)
if err != nil {
log.Fatal(err)
}
defer tmpFile.Close()
// 使用缓冲读写器
scanner := bufio.NewScanner(srcFile)
writer := bufio.NewWriter(tmpFile)
for scanner.Scan() {
line := scanner.Text()
newLine := strings.ReplaceAll(line, "DRUMCLASS", "False")
writer.WriteString(newLine + "\n")
}
writer.Flush()
// 检查扫描错误
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
// 关闭文件
srcFile.Close()
tmpFile.Close()
// 替换原文件
err = os.Rename(tmpPath, filePath)
if err != nil {
log.Fatal(err)
}
}
方法4:封装成函数
package main
import (
"io/ioutil"
"log"
"strings"
)
func sedReplace(filePath, oldStr, newStr string) error {
content, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
newContent := strings.ReplaceAll(string(content), oldStr, newStr)
return ioutil.WriteFile(filePath, []byte(newContent), 0644)
}
func main() {
err := sedReplace("/usr/share/OCTAVA/Rich/HTTP/CLASS", "DRUMCLASS", "False")
if err != nil {
log.Fatal(err)
}
}
注意事项
- 权限问题:确保Go程序有足够的权限读取和写入目标文件
- 错误处理:实际生产代码需要更完善的错误处理
- 并发安全:如果文件可能被其他进程访问,需要考虑文件锁
- 备份:重要文件操作前建议备份原文件
这些方法都能实现与sed -i -e "s/DRUMCLASS/False/g"相同的功能,其中方法1是最简单直接的实现。

