콘솔의 표준 입력에서 읽는 방법은 무엇입니까?


270

명령 줄에서 표준 입력을 읽으려고하지만 입력하라는 메시지가 표시되기 전에 프로그램이 종료되면서 시도가 끝났습니다. C #에서 Console.ReadLine () 에 해당하는 것을 찾고 있습니다.

이것이 내가 현재 가지고있는 것입니다 :

package main

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

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("Enter text: ")
    text, _ := reader.ReadString('\n')
    fmt.Println(text)

    fmt.Println("Enter text: ")
    text2 := ""
    fmt.Scanln(text2)
    fmt.Println(text2)

    ln := ""
    fmt.Sscanln("%v", ln)
    fmt.Println(ln)
}

이 코드는 올바르게 보입니다. 호기심으로 놀이터에서 이것을 실행하고 있습니까? Go Playground는 네트워킹 이유로 인해 표준 입력을 허용하지 않습니다.
LinearZoetrope 2018 년

신경 쓰지 마십시오. 포인터가 필요한 미묘한 문제 인 것 같습니다 (내 대답 참조). bufio.NewReader 메서드의 문제가 무엇인지 확실하지 않지만 저에게 효과적입니다.
LinearZoetrope 2019 년


8
밑줄 판독기 에서 직접 판독 (예 :에서 직접 판독)과 함께 bufio판독기 (예 :)의 버퍼링을 혼합하지 마십시오 . 버퍼링은 임의로 멀리 읽을 수 있습니다. (이 특정한 경우 나중에 동일한 버퍼에서 읽어야합니다). bufio.NewReader(os.Stdin)fmt.Scanln(x)os.Stdinfmt.Fscanln(reader,x)
Dave C

나는 fmt.Sscanln작품을 얻지 못했다. 실행 후 "% v"가된다
Beeno Tung

답변:


294

블록에 어떤 문제가 있는지 잘 모르겠습니다

reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter text: ")
text, _ := reader.ReadString('\n')
fmt.Println(text)

내 컴퓨터에서 작동합니다. 그러나 다음 블록의 경우 입력을 할당 할 변수에 대한 포인터가 필요합니다. 교체 시도 fmt.Scanln(text2)와 함께 fmt.Scanln(&text2). Sscanlnstdin 대신 메모리에 이미있는 문자열을 구문 분석하기 때문에을 사용하지 마십시오 . 당신이하려고했던 것과 같은 것을하고 싶다면, 그것을fmt.Scanf("%s", &ln)

그래도 문제가 해결되지 않으면 이상한 시스템 설정이나 버그가있는 IDE 일 수 있습니다.


2
그것들은 작은 따옴표로되어 있습니까? ReadString('\n')또는 ReadString("\n")?
425nesp

8
@ 425nesp 네, 이것은 1 바이트 인 델리 미터입니다. golang.org/pkg/bufio/#Reader.ReadString
LinearZoetrope

3
내가 백 스페이스를 사용하려고 할 때 좋은 대답은, 그러나 이것은 실패 등 키
kumarharsh

4
Golang은 리더 rd를 통해 파일 에서 변수 s로 행을 읽을 수 있습니다.if s,_ = rd.ReadString('\n'); true { s = strings.Trim(s, " \n") }
Nam G VU

2
흥미로운 것을 공유하기 만하면됩니다 (저는 Golang 초보자입니다) : \ n 작은 따옴표 안에 있어야합니다 (큰 따옴표를 사용하지 마십시오). 아니면, 이것을 재현 할 것입니다 :cannot use "\n" (type string) as type byte in argument to reader.ReadString
ivanleoncz

124

당신은뿐만 아니라 시도 할 수 있습니다 :

scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    fmt.Println(scanner.Text())
}

if scanner.Err() != nil {
    // handle error.
}

6
한 줄 입력 만 원하면 "for {}"를 제거 할 수 있습니다.
user2707671

3
for {} 루프가 있으면 입력 할 때 루프에서 어떻게 나오나요? for 루프를 중지시킬 특수 문자가 있습니까? -감사합니다
Madhan Ganesh

2
@Madhan scanner.Scan ()은 부울 값을 반환하여 for 루프의 종료 여부를 나타냅니다.
Helin Wang

5
입력이 64 * 1024 바이트보다 큰 경우 bufio.Scanner : token too long 이 오류가 발생 합니다. 또한 fmt.Println(scanner.Err())for 루프 아래에 추가하는 것을 잊지 마십시오 .
Yuvaraj Loganathan

"abc \ n ^ D"를 입력하면 예상되는 문자열은 "abc \ n"이지만 "abc"를 반환합니다.
Shivendra Mishra

96

이 작업을 수행하는보다 표준적인 방법은 다음과 같습니다.

package main

import "fmt"

func main() {
    fmt.Print("Enter text: ")
    var input string
    fmt.Scanln(&input)
    fmt.Print(input)
}

상기 살펴보세요 scangodoc을 : http://godoc.org/fmt#Scan

스캔은 표준 입력에서 읽은 텍스트를 스캔하여 연속 공백으로 구분 된 값을 연속 인수에 저장합니다. 줄 바꿈은 공백으로 계산됩니다.

Scanln은 스캔과 비슷하지만 줄 바꿈에서 스캔을 중지하며 마지막 항목 뒤에 줄 바꿈 또는 EOF가 있어야합니다.


10
이것은 입력 문자열에서 공백을 좋아하지 않는 것 같습니다.
Hairy Chris

3
@HairyChris 예, 이상합니다. 문서에서 그것은 stops scanning at a newline and after the final item there must be a newline or EOF왜 공간이 "깨지는"지 확실하지 않다고 말합니다. 그것은 그것이 버그라고 생각합니다
karantan

6
github.com/golang/go/issues/5703에 대한 버그가있었습니다. WorkingAsIntended 로 닫혔습니다. 또한보십시오 : stackoverflow.com/questions/24005899/…groups.google.com/forum/#!topic/golang-nuts/r6Jl4D9Juw0 많은 사람들이 이것에 문제가있는 것 같습니다. 설명서 변경이 필요하십니까? 또한 마지막 링크에서 : "Scan과 Scanln은 구문 분석을위한 것이므로 stdin에서 한 줄의 텍스트를 얻는 것만으로도 목적을 무산시킬 수 있습니다."
user2707671

나에게, 비슷한 기능을 가진 fmt.Scan이 bufio.NewReader와 같은 공간에서는 잘 작동하지 않는다는 것이 실제로 혼란 스럽습니다.
FilBot3

3
사용하는 동안 공간의 유적과 같은 문제 fmt.Scanlnfmt.Scan현재 2,016 이동 버전은 (go1.6.2 리눅스 / AMD64 버전을 이동).
Chiheb Nexus

30

콘솔에서 입력을 수집 할 때는 항상 bufio.NewScanner 를 사용하십시오 . 다른 사람들이 언급했듯이 여러 가지 방법으로 작업을 수행 할 수 있지만 스캐너는 원래 작업을 수행하도록되어 있습니다. Dave Cheney는 bufio.Reader의 ReadLine 대신 스캐너를 사용해야하는 이유를 설명합니다.

https://twitter.com/davecheney/status/604837853344989184?lang=en

다음은 귀하의 질문에 대한 코드 스 니펫 답변입니다

package main

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

/*
 Three ways of taking input
   1. fmt.Scanln(&input)
   2. reader.ReadString()
   3. scanner.Scan()

   Here we recommend using bufio.NewScanner
*/

func main() {
    // To create dynamic array
    arr := make([]string, 0)
    scanner := bufio.NewScanner(os.Stdin)
    for {
        fmt.Print("Enter Text: ")
        // Scans a line from Stdin(Console)
        scanner.Scan()
        // Holds the string that scanned
        text := scanner.Text()
        if len(text) != 0 {
            fmt.Println(text)
            arr = append(arr, text)
        } else {
            break
        }

    }
    // Use collected inputs
    fmt.Println(arr)
}

프로그래밍 방식으로 입력을 수집하지 않으려면 다음 행을 추가하십시오.

   scanner := bufio.NewScanner(os.Stdin)
   scanner.Scan()
   text := scanner.Text()
   fmt.Println(text)

위 프로그램의 출력은 다음과 같습니다.

Enter Text: Bob
Bob
Enter Text: Alice
Alice
Enter Text:
[Bob Alice]

위의 프로그램은 사용자 입력을 수집하여 배열에 저장합니다. 우리는 또한 특별한 흐름으로 그 흐름을 깨뜨릴 수 있습니다. 스캐너는 사용자 정의 기능 등을 사용한 분할, 다양한 유형의 I / O 스트림 (Stdin, String) 스캔 등 고급 사용을위한 API를 제공합니다.


이것은 정답입니다. 더 정확한 답변 일뿐만 아니라 더 나은 품질입니다.
다니엘 파렐

11

공백이있는 입력을 처리 할 수있는 루프 내에서 여러 입력을 읽는 또 다른 방법 :

package main
import (
    "fmt"
    "bufio"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    var text string
    for text != "q" {  // break the loop if text == "q"
        fmt.Print("Enter your text: ")
        scanner.Scan()
        text = scanner.Text()
        if text != "q" {
            fmt.Println("Your text was: ", text)
        }
    }
}

산출:

Enter your text: Hello world!
Your text was:  Hello world!
Enter your text: Go is awesome!
Your text was:  Go is awesome!
Enter your text: q

2
내부 "q"검사에서 중단을 사용하여 무한 루프로 모두 감쌀 수 있습니다. 그건 그렇고 좋은 답변입니다!
tebanep

2
for 루프에서 조건부도 제거 할 수있는 것처럼 보입니다.
irbanana

6

나는 파티에 늦었다. 그러나 하나의 라이너는 어떻습니까?

data, err := ioutil.ReadAll(os.Stdin)

명령 행에 입력이 입력되면 ctrl + d (EOT)를 누르십시오.


os.Stdin'종료'하지 않기 때문에 모든 것을 읽을 수는 없습니다. 당신은 잠시 기다려야 할 것입니다 ...
gypsydave5

2
ctrl + d, 즉 eot를 누릅니다.
Shivendra Mishra

3
그렇습니다 mail. 이메일로 글을 쓰는 것을 상기시킵니다 .
gypsydave5

5

이 코드를 사용해보십시오 :-

var input string
func main() {
      fmt.Print("Enter Your Name=")
      fmt.Scanf("%s",&input)
      fmt.Println("Hello "+input)
      }

3
Scanf()문자열에 공백을 허용하지 않는 것 같습니다
Eslam

4

다음과 같이 수행 할 수도 있습니다.

package main
import "fmt"     

func main(){
    var myname string
fmt.Scanf("%s", &myname)           
fmt.Println("Hello", myname)       
}

3

몇 가지 프롬프트 값을 깨끗하게 읽으십시오.

// Create a single reader which can be called multiple times
reader := bufio.NewReader(os.Stdin)
// Prompt and read
fmt.Print("Enter text: ")
text, _ := reader.ReadString('\n')
fmt.Print("Enter More text: ")
text2, _ := reader.ReadString('\n')
// Trim whitespace and print
fmt.Printf("Text1: \"%s\", Text2: \"%s\"\n",
    strings.TrimSpace(text), strings.TrimSpace(text2))

실행은 다음과 같습니다.

Enter text: Jim
Enter More text: Susie
Text1: "Jim", Text2: "Susie"

2
strings.TrimSpace는 '\ n'을 제거하기 때문에 좋은 방법입니다. 그리고 reader.ReadString ( '\ n')도 크로스 플랫폼이라고 생각합니다.
user2707671

@Naren Yellavula의 답변과 같은 NewScanner
John Balvin Arias

2

다음과 같이 스캔하려는 var에 대한 포인터를 제공해야합니다.

fmt.scan(&text2)

0

제 경우에는 watcher명령을 사용 하여 프로그램을 자동 실행 했기 때문에 프로그램이 대기하지 않았습니다 . 프로그램을 수동으로 실행하면 go run main.go"텍스트 입력"이 발생하고 결국 콘솔에 인쇄됩니다.

fmt.Print("Enter text: ")
var input string
fmt.Scanln(&input)
fmt.Print(input)

2
Scan*제품군 의 한계는 공백 (예 : 공백) 구분 기호를 읽는 것입니다.
George Tseres
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.