donglie1994
donglie1994
2012-12-09 17:36

读取一个文本文件,替换其单词,输出到另一个文本文件

  • string
  • replace
  • text
  • file
已采纳

So I am trying to make a program in GO to take a text file full of code and convert that into GO code and then save that file into a GO file or text file. I have been trying to figure out how to save the changes I made to the text file, but the only way I can see the changes is through a println statement because I am using strings.replace to search the string array that the text file is stored in and change each occurrence of a word that needs to be changed (ex. BEGIN -> { and END -> }). So is there any other way of searching and replacing in GO I don't know about or is there a way to edit a text file that I don't know about or is this impossible?

Thanks

Here is the code I have so far.

package main

import (
    "os"
    "bufio"
    "bytes"
    "io"
    "fmt"
    "strings"
)


func readLines(path string) (lines []string, errr error) {
    var (
        file *os.File
        part []byte
        prefix bool
    )
    if file, errr = os.Open(path); errr != nil {
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 0))
    for {
        if part, prefix, errr = reader.ReadLine(); errr != nil {
            break
        }
    buffer.Write(part)
        if !prefix {
            lines = append(lines, buffer.String())
            buffer.Reset()
        }
    }
    if errr == io.EOF {
        errr = nil
    }
    return
}

func writeLines(lines []string, path string) (errr error) {
    var (
        file *os.File
    )

    if file, errr = os.Create(path); errr != nil {
        return
    }
    defer file.Close()


    for _,item := range lines {

        _, errr := file.WriteString(strings.TrimSpace(item) + "
");

        if errr != nil {

            fmt.Println(errr)
            break
        }
    }

    return
}

func FixBegin(lines []string) (errr error) {
    var(
    a string

    )
for i := 0; ; i++ {
        a = lines[i];

        fmt.Println(strings.Replace(a, "BEGIN", "{", -1))
    }

    return
}

func FixEnd(lines []string) (errr error) {
    var(
    a string

    )
for i := 0; ; i++ {
        a = lines[i];

        fmt.Println(strings.Replace(a, "END", "}", -1))
    }
    return
}

func main() {
    lines, errr := readLines("foo.txt")
    if errr != nil {
        fmt.Println("Error: %s
", errr)
        return
    }
    for _, line := range lines {
        fmt.Println(line)
    }


    errr = FixBegin(lines)

    errr = writeLines(lines, "beer2.txt")
    fmt.Println(errr)

    errr = FixEnd(lines)
    lines, errr = readLines("beer2.txt")
    if errr != nil {
        fmt.Println("Error: %s
", errr)
        return
    }
    errr = writeLines(lines, "beer2.txt")
    fmt.Println(errr)
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

2条回答

  • dongwa3808 dongwa3808 9年前
    jnml@fsc-r630:~/src/tmp/SO/13789882$ ls
    foo.txt  main.go
    jnml@fsc-r630:~/src/tmp/SO/13789882$ cat main.go 
    package main
    
    import (
            "bytes"
            "io/ioutil"
            "log"
    )
    
    func main() {
            src, err := ioutil.ReadFile("foo.txt")
            if err != nil {
                    log.Fatal(err)
            }
    
            src = bytes.Replace(src, []byte("BEGIN"), []byte("{"), -1)
            src = bytes.Replace(src, []byte("END"), []byte("}"), -1)
            if err = ioutil.WriteFile("beer2.txt", src, 0666); err != nil {
                    log.Fatal(err)
            }
    }
    jnml@fsc-r630:~/src/tmp/SO/13789882$ cat foo.txt 
    BEGIN
      FILE F(KIND=REMOTE);
      EBCDIC ARRAY E[0:11];
      REPLACE E BY "HELLO WORLD!";
      WRITE(F, *, E);
    END.
    jnml@fsc-r630:~/src/tmp/SO/13789882$ go run main.go 
    jnml@fsc-r630:~/src/tmp/SO/13789882$ cat beer2.txt 
    {
      FILE F(KIND=REMOTE);
      EBCDIC ARRAY E[0:11];
      REPLACE E BY "HELLO WORLD!";
      WRITE(F, *, E);
    }.
    jnml@fsc-r630:~/src/tmp/SO/13789882$ 
    
    点赞 评论 复制链接分享
  • doushang1964 doushang1964 9年前

    I agree with @jnml wrt using ioutil to slurp the file and to write it back. But I think that the replacing shouldn't be done by multiple passes over []byte. Code and data are strings/text and should be treated as such (even if dealing with non ascii/utf8 encodings requires estra work); a one pass replacement (of all placeholders 'at once') avoids the risk of replacing results of previous changes (even if my regexp proposal must be improved to handle non-trivial tasks).

    package main
    
    import(
        "fmt"
        "io/ioutil"
        "log"
        "regexp"
        "strings"
    )
    
    func main() {
        // (1) slurp the file
        data, err := ioutil.ReadFile("../tmpl/xpl.go")
        if err != nil {
            log.Fatal("ioutil.ReadFile: ", err)
        }
        s := string(data)
        fmt.Printf("----
    %s----
    ", s)
        // => function that works for files of (known) other encodings that ascii or utf8
    
        // (2) create a map that maps placeholder to be replaced to the replacements
        x := map[string]string {
            "BEGIN" : "{",
            "END" : "}"}
        ks := make([]string, 0, len(x))
        for k := range x {
            ks = append(ks, k)
        }
        // => function(s) that gets the keys from maps
    
        // (3) create a regexp that finds the placeholder to be replaced
        p := strings.Join(ks, "|")
        fmt.Printf("/%s/
    ", p)
        r := regexp.MustCompile(p)
        // => funny letters & order need more consideration
    
        // (4) create a callback function for ..ReplaceAllStringFunc that knows
        // about the map x
        f := func(s string) string {
            fmt.Printf("*** '%s'
    ", s)
            return x[s]
        }
        // => function (?) to do Step (2) .. (4) in a reusable way
    
        // (5) do the replacing (s will be overwritten with the result)
        s = r.ReplaceAllStringFunc(s, f)
        fmt.Printf("----
    %s----
    ", s)
    
        // (6) write back
        err = ioutil.WriteFile("result.go", []byte(s), 0644)
        if err != nil {
            log.Fatal("ioutil.WriteFile: ", err)
        }
        // => function that works for files of (known) other encodings that ascii or utf8
    }
    

    output:

    go run 13789882.go
    ----
    func main() BEGIN
    END
    ----
    /BEGIN|END/
    *** 'BEGIN'
    *** 'END'
    ----
    func main() {
    }
    ----
    
    点赞 评论 复制链接分享