Golang从标准输入读取多个字段的方法

huangapple go评论78阅读模式
英文:

Golang reading multiple fields from stdin line

问题

$ echo "A 1 2 3 4" | go run test.go
整行内容: A
下一个字段: A

我需要从标准输入中读取几行内容,格式类似于"A 1 2 3 4"(目前代码只处理一行),但是出现了一些问题。Scanln应该读取整行内容,而Fields应该按空格分割字符串?为什么Scanln只读取了一个单词?

package main

import (
    "fmt"
    "strings"
)

func main() {
    var line string
    fmt.Scanln(&line)
    fmt.Println("整行内容: ", line)
    for _, x := range strings.Fields(line) {
        fmt.Println("下一个字段: ", x)
    }
}

$ echo "A 1 2 3 4" | go run test.go
整行内容: A
下一个字段: A

英文:
$ echo "A 1 2 3 4" | go run test.go 
entire:  A
next field:  A

I need to read several lines from standard input that are like "A 1 2 3 4" (code does one line for now) and something goes wrong. Scanln should read the entire line and Fields should split it by newlines? Why does Scanln read only one word?

package main

import (
    "fmt"
    "strings"
)

func main() {
    var line string
    fmt.Scanln(&line)
    fmt.Println("entire: ",line)
    for _,x := range strings.Fields(line) {
        fmt.Println("next field: ",x)
    }
}

$ echo "A 1 2 3 4" | go run test.go 
entire:  A
next field:  A

答案1

得分: 6

你试过这样吗:

package main

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

func main() {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line = scanner.Text()
		fmt.Println("Got line:", line)
		for _, x := range strings.Fields(line) {
			fmt.Println("next field:",x)
		}
	}
}

然后:

$ printf "aa bb \n cc dd " | go run 1.go  
Got line: aa bb
next field:  aa
next field:  bb
Got line:  cc dd
next field:  cc
next field:  dd
英文:

Have you tried:

package main

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

func main() {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line = scanner.Text()
		fmt.Println("Got line:", line)
		for _, x := range strings.Fields(line) {
			fmt.Println("next field: ",x)
		}
	}
}

Then:

$ printf "aa bb \n cc dd " | go run 1.go  
Got line: aa bb
next field:  aa
next field:  bb
Got line:  cc dd
next field:  cc
next field:  dd

答案2

得分: 2

如果你想将每个输入存储到单独的变量中,你可以尝试以下代码:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	var a, b string
	var c int
	var r = bufio.NewReader(os.Stdin)
	fmt.Fscanf(r, "%s %s %d", &a, &b, &c)
	fmt.Printf("%s %s %d", a, b, c)
}

它将输出以下结果:

//给定输入
w r 4
//输出
w r 4
英文:

In case you want to store each input to a seperate variable you can try this:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	var a, b string
	var c int
	var r = bufio.NewReader(os.Stdin)
	fmt.Fscanf(r, "%s %s %d", &a, &b, &c)
	fmt.Printf("%s %s %d", a, b, c)
}

It will give the following output:

//given input
w r 4
//output
w r 4

</details>



# 答案3
**得分**: 1

我被另一个问题的答案误导了,它说`Scanln`会读取整行。不,`Scanln`只是一个读取单词(以空格分隔的字符串)的`Scan`函数,并且只会读取与实际变量数量相匹配的单词,遇到换行符就停止解析。在Go语言中,相当于`readline`的等效函数让人感到非常困惑。

<details>
<summary>英文:</summary>

I got mislead by another question&#39;s answer that said `Scanln` reads an entire line. No, Scanln is only a Scan that reads words (space separated strings) and as many as actual variables specified, but quits parsing on a newline. Its totally confusing what the readline equivalent would be in Go.

</details>



# 答案4
**得分**: 0

我意识到这是一个旧问题,但我正在寻找相同的内容,并意识到我们可以对解释进行改进。

实际上,原帖作者@ArekBulski的评论给了我线索,他说:

&gt; Scanln只是一个读取单词(以空格分隔的字符串)并且与参数中指定的实际变量数量相同的扫描器

Scanln()会读取整行内容,但它只会保存与参数中变量数量相等的字符串数量。因此,对于"A 1 2 3 4",`fmt.Scanln(&amp;var1)`只会保存"A",`fmt.Scanln(&amp;var1, &amp;var2)`只会分别保存"A"和"1"到var1和var2中。

因此,当你知道要输入的变量数量时,`fmt.Scanln(a ...interface{})`是一个很好的选择,否则`bufio.NewScanner(os.Stdin)`可能更适合。

<details>
<summary>英文:</summary>

I realize this is an old question, but I was searching for the same thing and realized that we could improve to the explanation.

It was actually the comment from original poster @ArekBulskithat gave me the clue when he said 

&gt; Scanln is only a Scan that reads words (space separated strings) and as many as actual variables specified

Scanln() will read the entire line, but it only saves the number of strings equal to the number of variables in the parameters so for &quot;A 1 2 3 4&quot; `fmt.Scanln(&amp;var1)` will only store &quot;A&quot; and `fmt.Scanln(&amp;var1, &amp;var2)` will only store &quot;A&quot; and &quot;1&quot; in var1 and var2 respectively.

Hence `fmt.Scanln(a ...interface{})` is a good fit when you know the number of variables coming in, otherwise `bufio.NewScanner(os.Stdin)` might be a better fit.

</details>



huangapple
  • 本文由 发表于 2017年4月11日 23:28:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/43350234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定