1

编写了一个调用“ls”的简单程序,然后通过正则表达式过滤以“s”结尾的文件传递每一行。ls 仅用于学习 exec 包的目的。我怎样才能改进下面的代码更正确/简洁/go-ish?

package main

import (
    "bufio"
    "fmt"
    "os/exec"
    "regexp"
)

func main() {

    cmd := exec.Command("ls")
    stdout, _ := cmd.StdoutPipe()
    s := bufio.NewReader(stdout)
    cmd.Start()

    go cmd.Wait()

    for {
        l, _, err := s.ReadLine()
        if err != nil {
            break
        }

        if m, err := regexp.Match(".*s$", l); m && err == nil {
            fmt.Println(string(l))
        }
    }
}
4

3 回答 3

3

标准文档中的Cmd.Output 示例非常简洁。它不进行任何文本处理,但它显示了如何执行命令并通过单个函数调用获取输出。

这是一种将该示例与您的示例相结合的方法,

package main

import (
    "bytes"
    "fmt"
    "log"
    "os/exec"
    "regexp"
)

func main() {
    out, err := exec.Command("ls").Output()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Print(string(bytes.Join(regexp.MustCompile(".*s\n").FindAll(out, -1), nil)))
}

如果目标是对软件包有一个广泛的了解,请尝试一些功能和方法来了解它们的不同功能。试验命令参数。试验 Cmd 结构的不同字段。尽量不要对正则表达式等其他包过于分心,只需寻找最简单的示例即可使用包功能。

当然,如果您看到如何在实际应用程序中使用 exec 功能,请尝试一下。您将更深入地了解该功能。

于 2012-06-05T17:30:23.137 回答
2

为此类示例添加错误检查并停止使用正则表达式。

对于任何大于缓冲区大小的输入数据,ReadLine 将不可避免地在某个时候返回 isPrefix 设置为 true。ReadString('\n') 做你想做的事——读到行尾,不管它是否适合缓冲区,按原样扩展输出字符串。这也意味着你可能会得到一个任意长的字符串。对 ReadLine() 有利的一面是,它确实会为您从行尾删除“\n”或“\r\n”,因此在使用 ReadString() 时,我们必须自己做。

package main

import (
    "bufio"
    "fmt"
    "os/exec"
    "io"
)

func main() {
    var err error
    var out io.Reader

    // Create a command object
    cmd := exec.Command("ls")

    // Obtain a pipe to receive the stdout of the command
    out, err = cmd.StdoutPipe(); if err != nil {
        panic(err)
    }

    // Start the child process
    err = cmd.Start(); if err != nil {
        panic(err)
    }

    // bufio.Reader allows us to read all bytes until newline
    s := bufio.NewReader(out)
    for {
        var line string
        line, err = s.ReadString('\n')
        if err == io.EOF && len(line) == 0 {
            // Good end of file with no partial line
            break
        }
        if err == io.EOF {
            err := fmt.Errorf("Last line not terminated: %q", line)
            panic(err)
        }
        if err != nil {
            panic(err)
        }
        line = line[:len(line)-1]       // drop the '\n'
        if line[len(line)-1] == '\r' {
            line = line[:len(line)-1]   // drop the '\r'
        }
        if line[len(line)-1] == 's' {   // Finally check for lines ending in 's'
            fmt.Println(line)
        }
    }

    // Wait for the result of the command; also closes our end of the pipe
    err = cmd.Wait()
    if err != nil {
        panic(err)
    }
}
于 2012-06-11T14:59:20.263 回答
0

例如,

package main

import (
    "bufio"
    "errors"
    "fmt"
    "io"
    "os/exec"
)

func main() {
    cmd := exec.Command("ls")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
        return
    }
    ls := bufio.NewReader(stdout)
    err = cmd.Start()
    if err != nil {
        fmt.Println(err)
        return
    }
    for {
        line, isPrefix, err := ls.ReadLine()
        if isPrefix {
            fmt.Println(errors.New("isPrefix: true"))
            return
        }
        if err != nil {
            if err != io.EOF {
                fmt.Println(err)
                return
            }
            break
        }
        fmt.Println(string(line))
    }
    err = cmd.Wait()
    if err != nil {
        fmt.Println(err)
        return
    }
}

输出(取决于您的目录内容):

bench.go
temp.go
于 2012-06-05T15:05:58.830 回答