73 lines
1.4 KiB
Go
73 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
if err := removeLines("foobar.txt", 1, 2); err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
}
|
|
|
|
func removeLines(fn string, start, n int) (err error) {
|
|
if start < 1 {
|
|
return errors.New("invalid request. line numbers start at 1.")
|
|
}
|
|
if n < 0 {
|
|
return errors.New("invalid request. negative number to remove.")
|
|
}
|
|
var f *os.File
|
|
if f, err = os.OpenFile(fn, os.O_RDWR, 0); err != nil {
|
|
return
|
|
}
|
|
defer func() {
|
|
if cErr := f.Close(); err == nil {
|
|
err = cErr
|
|
}
|
|
}()
|
|
var b []byte
|
|
if b, err = ioutil.ReadAll(f); err != nil {
|
|
return
|
|
}
|
|
cut, ok := skip(b, start-1)
|
|
if !ok {
|
|
return fmt.Errorf("less than %d lines", start)
|
|
}
|
|
if n == 0 {
|
|
return nil
|
|
}
|
|
tail, ok := skip(cut, n)
|
|
if !ok {
|
|
return fmt.Errorf("less than %d lines after line %d", n, start)
|
|
}
|
|
t := int64(len(b) - len(cut))
|
|
if err = f.Truncate(t); err != nil {
|
|
return
|
|
}
|
|
if len(tail) > 0 {
|
|
_, err = f.WriteAt(tail, t)
|
|
}
|
|
return
|
|
}
|
|
|
|
func skip(b []byte, n int) ([]byte, bool) {
|
|
for ; n > 0; n-- {
|
|
if len(b) == 0 {
|
|
return nil, false
|
|
}
|
|
x := bytes.IndexByte(b, '\n')
|
|
if x < 0 {
|
|
x = len(b)
|
|
} else {
|
|
x++
|
|
}
|
|
b = b[x:]
|
|
}
|
|
return b, true
|
|
}
|