Go的分页输出

Go的分页输出,go,stdout,pager,Go,Stdout,Pager,我正在尝试使用$PAGER从golang打印stdout,或者手动调用或多或少的命令,以允许用户轻松地滚动浏览许多选项。如何实现这一点?您可以使用该软件包启动一个运行较少的进程或$PAGER中的任何进程,然后将字符串传输到其标准输入。以下几点对我很有用: func main() { // Could read $PAGER rather than hardcoding the path. cmd := exec.Command("/usr/bin/less") // F

我正在尝试使用$PAGER从golang打印stdout,或者手动调用或多或少的命令,以允许用户轻松地滚动浏览许多选项。如何实现这一点?

您可以使用该软件包启动一个运行较少的进程或$PAGER中的任何进程,然后将字符串传输到其标准输入。以下几点对我很有用:

func main() {
    // Could read $PAGER rather than hardcoding the path.
    cmd := exec.Command("/usr/bin/less")

    // Feed it with the string you want to display.
    cmd.Stdin = strings.NewReader("The text you want to show.")

    // This is crucial - otherwise it will write to a null device.
    cmd.Stdout = os.Stdout

    // Fork off a process and wait for it to terminate.
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
}
您可以使用该包启动运行较少的进程或$PAGER中的任何进程,然后通过管道将字符串传输到其标准输入。以下几点对我很有用:

func main() {
    // Could read $PAGER rather than hardcoding the path.
    cmd := exec.Command("/usr/bin/less")

    // Feed it with the string you want to display.
    cmd.Stdin = strings.NewReader("The text you want to show.")

    // This is crucial - otherwise it will write to a null device.
    cmd.Stdout = os.Stdout

    // Fork off a process and wait for it to terminate.
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
}
下面是一个有点幼稚的cat示例,它在设置时使用$PAGER

package main

import (
        "io"
        "log"
        "os"
        "os/exec"
)

func main() {
        var out io.WriteCloser
        var cmd *exec.Cmd

        if len(os.Args) != 2 {
                log.Fatal("Wrong number of args: gcat <file>")
        }
        fileName := os.Args[1]
        file, err := os.Open(fileName)
        if err != nil {
                log.Fatal("Error opening file: ", err)
        }

        pager := os.Getenv("PAGER")

        if pager != "" {
                cmd = exec.Command(pager)

                var err error
                out, err = cmd.StdinPipe()
                if err != nil {
                        log.Fatal(err)
                }

                cmd.Stdout = os.Stdout

                if err := cmd.Start(); err != nil {
                        log.Fatal("Unable to start $PAGER: ", err)
                }

        } else {
                out = os.Stdout
        }

        _, err = io.Copy(out, file)
        if err != nil {
                log.Fatal(err)
        }

        file.Close()
        out.Close()

        if cmd != nil {
                if err := cmd.Wait(); err != nil {
                        log.Fatal("Error waiting for cmd: ", err)
                }
        }

}
下面是一个有点幼稚的cat示例,它在设置时使用$PAGER

package main

import (
        "io"
        "log"
        "os"
        "os/exec"
)

func main() {
        var out io.WriteCloser
        var cmd *exec.Cmd

        if len(os.Args) != 2 {
                log.Fatal("Wrong number of args: gcat <file>")
        }
        fileName := os.Args[1]
        file, err := os.Open(fileName)
        if err != nil {
                log.Fatal("Error opening file: ", err)
        }

        pager := os.Getenv("PAGER")

        if pager != "" {
                cmd = exec.Command(pager)

                var err error
                out, err = cmd.StdinPipe()
                if err != nil {
                        log.Fatal(err)
                }

                cmd.Stdout = os.Stdout

                if err := cmd.Start(); err != nil {
                        log.Fatal("Unable to start $PAGER: ", err)
                }

        } else {
                out = os.Stdout
        }

        _, err = io.Copy(out, file)
        if err != nil {
                log.Fatal(err)
        }

        file.Close()
        out.Close()

        if cmd != nil {
                if err := cmd.Wait(); err != nil {
                        log.Fatal("Error waiting for cmd: ", err)
                }
        }

}

我假设您已经有了从程序打印到标准输出的输出,您希望捕获这些输出并将其发送到寻呼机,但您不想这样做 重写I/O以使用其他响应所需的其他输入流

通过将一面连接到寻呼机,另一面连接到标准输出,您可以创建一个操作系统管道,其工作原理与使用| less运行命令相同,如下所示:

// Create a pipe for a pager to use
r, w, err := os.Pipe()
if err != nil {
    panic("You probably want to fail more gracefully than this")
}

// Capture STDOUT for the Pager. Keep the old
// value so we can restore it later.
stdout := os.Stdout
os.Stdout = w

// Create the pager process to execute and attach
// the appropriate I/O streams.
pager := exec.Command("less")
pager.Stdin = r
pager.Stdout = stdout // the pager uses the original stdout, not the pipe
pager.Stderr = os.Stderr

// Defer a function that closes the pipe and invokes
// the pager, then restores os.Stdout after this function
// returns and we've finished capturing output.
//
// Note that it's very important that the pipe is closed,
// so that EOF is sent to the pager, otherwise weird things 
// will happen.
defer func() {
    // Close the pipe
    w.Close()
    // Run the pager
    if err := pager.Run(); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    // restore stdout
    os.Stdout = stdout
}()

我假设您已经有了从程序打印到标准输出的输出,您希望捕获这些输出并将其发送到寻呼机,但您不想这样做 重写I/O以使用其他响应所需的其他输入流

通过将一面连接到寻呼机,另一面连接到标准输出,您可以创建一个操作系统管道,其工作原理与使用| less运行命令相同,如下所示:

// Create a pipe for a pager to use
r, w, err := os.Pipe()
if err != nil {
    panic("You probably want to fail more gracefully than this")
}

// Capture STDOUT for the Pager. Keep the old
// value so we can restore it later.
stdout := os.Stdout
os.Stdout = w

// Create the pager process to execute and attach
// the appropriate I/O streams.
pager := exec.Command("less")
pager.Stdin = r
pager.Stdout = stdout // the pager uses the original stdout, not the pipe
pager.Stderr = os.Stderr

// Defer a function that closes the pipe and invokes
// the pager, then restores os.Stdout after this function
// returns and we've finished capturing output.
//
// Note that it's very important that the pipe is closed,
// so that EOF is sent to the pager, otherwise weird things 
// will happen.
defer func() {
    // Close the pipe
    w.Close()
    // Run the pager
    if err := pager.Run(); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    // restore stdout
    os.Stdout = stdout
}()
此版本为所有要分页的输出创建一个名为pager的io.Writer。如果愿意,您可以将其分配给os.Stdout,并正确关闭它,并在main返回时等待$pager

此版本为所有要分页的输出创建一个名为pager的io.Writer。如果愿意,您可以将其分配给os.Stdout,并正确关闭它,并在main返回时等待$pager


这个问题很不清楚。如果您打印到标准输出,并且用户手动调用寻呼机,那么。。。你已经实现了你想要的。我想这个问题很好地解释了我想要什么。我试图实现的是将我的go程序的标准连接到$PAGER呼叫。这个问题非常不清楚。如果您打印到标准输出,并且用户手动调用寻呼机,那么。。。你已经实现了你想要的。我想这个问题很好地解释了我想要什么。据ls I称,我试图实现的是在2012年10月前将我的go程序的stdout传输到$PAGERYears。我模模糊糊地记得,实际使用它时存在一些问题,例如,我尝试将它添加到godoc中,使其与启用寻呼机扩展的hg man一样,但我最终还是通过命令行上的一个寻呼机进行了管道传输。你可以通过w向进程写入任意代码。你是对的,根据ls I,你可以:pager:=os.ExpandEnv$pageryear2012年10月之前。我模模糊糊地记得,实际使用它时存在一些问题,例如,我尝试将它添加到godoc中,使其与启用寻呼机扩展的hg man一样,但我最终还是通过命令行上的一个寻呼机进行了管道传输。您可以通过w向进程写入任意代码。您是对的,您可以:pager:=os.ExpandEnv$PAGERah,它已关闭。关闭,我丢失了。这可以让你使用更少的导航,而不会弄乱upah,它已经过时了。我错过了。这样可以减少导航,而不会造成混乱