【问题标题】:Jump to specific line in file in Go在 Go 中跳转到文件中的特定行
【发布时间】:2016-02-13 12:40:41
【问题描述】:

在 Go 中是否可以跳转到文件中的特定行号并删除它? python中的linecache之类的东西。

我正在尝试匹配文件中的一些子字符串并删除相应的行。我已经处理了匹配的部分,并且我有一个需要删除行号的数组,但我一直不知道如何删除文件中的匹配行。

【问题讨论】:

  • 没有迭代没有办法直接跳转到一行。不过,可以使用Seek()ReadAt() 跳转到偏移量(字节长度)。为什么不逐行读取输入文件并将这些行写入新文件,而忽略与您的子字符串匹配的行?

标签: file csv go


【解决方案1】:

这是一个老问题,但如果有人正在寻找解决方案,我编写了一个包来处理文件中的任何行。 Link here。它可以打开一个文件并寻找任何行位置,而无需将整个文件读入内存并进行拆分。

import "github.com/stoicperlman/fls"

// This is just a wrapper around os.OpenFile. Alternatively 
// you could open from os.File and use fls.LineFile(file) to get f
f, err := fls.OpenFile("test.log", os.O_CREATE|os.O_WRONLY, 0600)
defer f.Close()

// return begining line 1/begining of file
// equivalent to f.Seek(0, io.SeekStart)
pos, err := f.SeekLine(0, io.SeekStart)

// return begining line 2
pos, err := f.SeekLine(1, io.SeekStart)

// return begining of last line
pos, err := f.SeekLine(0, io.SeekEnd) 

// return begining of second to last line
pos, err := f.SeekLine(-1, io.SeekEnd) 

不幸的是,我不确定您将如何删除,这只是将您带到文件中的正确位置。对于您的情况,您可以使用它转到要删除的行并保存位置。然后寻找下一行并保存。您现在可以删除该行的书尾。

// might want lineToDelete - 1
// this acts like 0 based array
pos1, err := f.SeekLine(lineToDelete, io.SeekStart)

// skip ahead 1 line
pos2, err := f.SeekLine(1, io.SeekCurrent)

// pos2 will be the position of the first character in next line
// might want pos2 - 1 depending on how the function works
DeleteBytesFromFileFunction(f, pos1, pos2)

【讨论】:

    【解决方案2】:

    根据我对 linecache 模块的读取,它获取一个文件并根据 '\n' 行结尾将其分解为一个数组。您可以使用 stringsbytes 在 Go 中复制相同的行为。您还可以使用bufio 库逐行读取文件并仅存储或保存您想要的行。

    package main
    
    import (
        "bytes"
        "fmt"
    )
    import "io/ioutil"
    
    func main() {
    
        b, e := ioutil.ReadFile("filename.txt")
        if e != nil {
            panic(e)
        }
        array := bytes.Split(b, []byte("\n"))
    
        fmt.Printf("%v", array)
    }
    

    【讨论】:

    • 谢谢。 Textarea 不是我喜欢的 IDE :)。
    • 如果某行包含 \r\n 怎么办?
    【解决方案3】:

    我写了一个小函数,允许您从文件中删除特定行。

    package main
    
    import (
        "io/ioutil"
        "os"
        "strings"
    )
    
    func main() {
        path := "path/to/file.txt"
        removeLine(path, 2)
    }
    
    func removeLine(path string, lineNumber int) {
        file, err := ioutil.ReadFile(path)
        if err != nil {
            panic(err)
        }
    
        info, _ := os.Stat(path)
        mode := info.Mode()
    
        array := strings.Split(string(file), "\n")
        array = append(array[:lineNumber], array[lineNumber+1:]...)
        ioutil.WriteFile(path, []byte(strings.Join(array, "\n")), mode)
    }
    

    【讨论】:

    • 这不是内存效率
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 2010-10-11
    • 1970-01-01
    • 2019-05-08
    • 1970-01-01
    • 2023-01-25
    • 2011-12-16
    相关资源
    最近更新 更多