如果某些字符串通过管道传递到其STDIN,则我需要一个命令行实用程序来表现不同。 这是一些最小的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main // file test.go import ( "fmt" "io/ioutil" "os" ) func main() { bytes, _ := ioutil.ReadAll(os.Stdin) if len(bytes) > 0 { fmt.Println("Something on STDIN:" + string(bytes)) } else { fmt.Println("Nothing on STDIN") } } |
如果您这样称呼它,效果很好:
1 | echo foo | go run test.go |
如果在STDIN上没有任何调用
1 | bytes, _ := ioutil.ReadAll(os.Stdin) |
...等待
我需要怎么做才能做到这一点?
提前致谢!
- 您是否尝试用bufio.reader或类似的东西包装stdin?还是用偷看看看是否有什么要读书的?
- 阅读文档:ReadAll一直进行到出现错误或EOF为止,因此请问自己:从stdin读取时是否出错? EOF? (您可以在终端中发送EOF,在Unix上按Control-D,在Windows上进行其他操作)
- @loreb我阅读了文档。您描述的是我做过的同样的事情,没有提到任何新内容。
- @Not_a_Golfer虐待尝试一下,到目前为止谢谢
- @sontags嗯?对不起,那我一定是误解了你的问题。它没有看到EOF,因为很明显,键盘仍然存在,因此您必须从键盘(Unix中的control-D)发送EOF或一次一行一行地读取输出。
- @loreb对不起,可能我还不够清楚:我知道这样的事实,为了通过该ReadAll,必须有一个EOF或一个错误。是的,CTRL + D发送EOF,但这不是可用性的选择。因此,很可能ReadAll是错误的方法,这只是为了说明结果。我基本上要求提供一些提示,以实现预期的行为。
- 确定Stdin是否具有Go数据的可能重复项
我通过使用os.ModeCharDevice解决了这个问题:
1 2 3 4 5 6 | stat, _ := os.Stdin.Stat() if (stat.Mode() & os.ModeCharDevice) == 0 { fmt.Println("data is being piped to stdin") } else { fmt.Println("stdin is from a terminal") } |
- 不确定这是否适用,例如/ dev / null
- 经过测试,如果您从/ dev / null传递标准输入(即./foo
- 我比@ NickCraig-Wood更喜欢此解决方案,因为它使用标准的go包。
使用code.google.com/p/go.crypto/ssh/terminal(为
这是一个更加集中的软件包。
如果stdin是一个终端/ tty,那么您就不是管道用户了,您可以做一些不同的事情。
这是一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | package main import ( "fmt" "github.com/andrew-d/go-termutil" "io" "os" ) func main() { if termutil.Isatty(os.Stdin.Fd()) { fmt.Println("Nothing on STDIN") } else { fmt.Println("Something on STDIN") io.Copy(os.Stdout, os.Stdin) } } |
测试中
1 2 3 4 5 6 7 8 | $ ./isatty Nothing on STDIN $ echo"hello" | ./isatty Something on STDIN hello $ (sleep 1 ; echo"hello") | ./isatty Something on STDIN hello |
- 你能举个例子吗?
- 提供@sontags示例!
如果以上方法都不适合您,请尝试以下方式:
1 2 3 4 5 6 7 | stat, err := os.Stdin.Stat() if err != nil { return nil, fmt.Errorf("you have an error in stdin:%s", err) } if (stat.Mode() & os.ModeNamedPipe) == 0 { return nil, errors.New("you should pass smth to stdin") } |
它在darwin(Mac OS)和linux(Ubuntu)中都对我有用。
-
$ go run sotest.go < sotest.go 产生you should pass smth to stdin 。ModeCharDevice 的答案行为符合预期。
这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package main // file test.go import ( "bufio" "fmt" "os" ) func main() { in := bufio.NewReader(os.Stdin) stats, err := os.Stdin.Stat() if err != nil { fmt.Println("file.Stat()", err) } if stats.Size() > 0 { in, _, err := in.ReadLine() if err != nil { fmt.Println("reader.ReadLine()", err) } fmt.Println("Something on STDIN:" + string(in)) } else { fmt.Println("Nothing on STDIN") } } |
谢谢@Kluyg!
-
( sleep 1 ; echo"hello" ) | .test 不起作用,打印Nothing on STDIN 。 我认为您不会获得这种方法来可靠地工作。