Jump to specific line in file in Go

huangapple go评论83阅读模式
英文:

Jump to specific line in file in Go

问题

在Go语言中,是否可以跳转到文件的特定行号并删除它?类似于Python中的linecache

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

英文:

In Go is it possible to jump to particular line number in a file and delete it? Something like linecache in python.

I'm trying to match some substrings in a file and remove the corresponding lines. The matching part I've taken care of and I have an array with line numbers I need to delete but I'm stuck on how to delete the matching lines in the file.

答案1

得分: 1

这是一个旧问题,但如果有人正在寻找解决方案,我写了一个处理文件中任意行的包。链接在这里。它可以打开文件并定位到任意行的位置,而无需将整个文件读入内存并分割。

import "github.com/stoicperlman/fls"

// 这只是对os.OpenFile的包装。或者你可以从os.File打开并使用fls.LineFile(file)获取f
f, err := fls.OpenFile("test.log", os.O_CREATE|os.O_WRONLY, 0600)
defer f.Close()

// 返回第一行/文件的开头
// 等同于 f.Seek(0, io.SeekStart)
pos, err := f.SeekLine(0, io.SeekStart)

// 返回第二行的开头
pos, err := f.SeekLine(1, io.SeekStart)

// 返回最后一行的开头
pos, err := f.SeekLine(0, io.SeekEnd)

// 返回倒数第二行的开头
pos, err := f.SeekLine(-1, io.SeekEnd)

不幸的是,我不确定如何删除行,这只是处理文件中正确位置的部分。对于你的情况,你可以使用它来定位到要删除的行并保存位置。然后定位到下一行并保存位置。现在你有了要删除的行的起始和结束位置。

// 可能需要 lineToDelete - 1
// 这就像基于0的数组
pos1, err := f.SeekLine(lineToDelete, io.SeekStart)

// 跳过1行
pos2, err := f.SeekLine(1, io.SeekCurrent)

// pos2将是下一行第一个字符的位置
// 根据函数的工作方式,可能需要 pos2 - 1
DeleteBytesFromFileFunction(f, pos1, pos2)
英文:

This is an old question, but if anyone is looking for a solution I wrote a package that handles going to any line in a file. Link here. It can open a file and seek to any line position without reading the whole file into memory and splitting.

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) 

Unfortunately I'm not sure how you would delete, this just handles getting you to the correct position in the file. For your case you could use it to go to the line you want to delete and save the position. Then seek to the next line and save that as well. You now have the bookends of the line to delete.

// 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

得分: 0

根据我对linecache模块的了解,它会根据'\n'换行符将文件拆分为数组。你可以在Go中通过使用stringsbytes来复制相同的行为。你也可以使用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)
}
英文:

Based on my read of the linecache module it takes a file and explodes it into an array based on '\n' line endings. You could replicate the same behavior in Go by using strings or bytes. You could also use the bufio library to read a file a line by line and only store or save the lines you want.

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)
}

答案3

得分: -1

我写了一个小函数,可以从文件中删除特定的行。

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)
}

这段代码是一个示例,它定义了一个名为removeLine的函数,用于从文件中删除指定的行。函数接受两个参数:文件路径和要删除的行号。它首先读取文件内容,然后将其按行分割成一个字符串数组。然后,它使用给定的行号从数组中删除相应的行。最后,它将修改后的内容写回到文件中。

请注意,这只是一个简单的示例,没有进行错误处理和边界检查。在实际使用中,你可能需要添加适当的错误处理和边界检查来确保代码的健壮性。

英文:

I wrote a small function that allowing you remove from a file a specific line.

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)
}

huangapple
  • 本文由 发表于 2016年2月13日 20:40:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/35379958.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定