2015-06-14 2 views
1

Мне нужно, чтобы пользователь вводил многострочный текст в консоль.многострочный ввод в терминале Перейти к применению

Вот мой код:

package main 

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

func main() { 
    for { 
     fmt.Println("How to read all lines here?") 
     in := bufio.NewReader(os.Stdin) 
     result, err := in.ReadString('\n') 
     if err != nil { 
      fmt.Println(err) 
     } 
     fmt.Println("\nresult") 
     fmt.Println(result)  

    } 
} 

я вставил в консоли:

Hello 
    World 

Он выводит:

How to read all lines here? 

     Hello 
     World 


result 


How to read all lines here? 

result 
     Hello 

How to read all lines here? 

result 
     World 

How to read all lines here? 

result 


How to read all lines here? 

Но я ожидаю, что это будет:

  How to read all lines here? 

       Hello 
       World 


     result 


     How to read all lines here? 

     result 
       Hello 
       World 

     How to read all lines here? 

Я думаю, мне нужно использовать что-то вроде EOF вместо '\n' Но как это сделать?

Update

ответ peterSo работает только в том случае, когда я пытаюсь вставить из буфера обмена текст с одним или несколькими пустыми строками в-между, например:

Hello 

World 

Он печатает

Enter Lines: 
Hello 

WorldResult: 
Hello 

Enter Lines: 

Обновление 2

Замечательный обновленный ответ peterSO теперь работает даже для te xt с пустыми строками.

ответ

4

Буфер набор линий и определить конец набора линий. Например,

package main 

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

func main() { 
    scn := bufio.NewScanner(os.Stdin) 
    for { 
     fmt.Println("Enter Lines:") 
     var lines []string 
     for scn.Scan() { 
      line := scn.Text() 
      if len(line) == 1 { 
       // Group Separator (GS ^]): ctrl-] 
       if line[0] == '\x1D' { 
        break 
       } 
      } 
      lines = append(lines, line) 
     } 

     if len(lines) > 0 { 
      fmt.Println() 
      fmt.Println("Result:") 
      for _, line := range lines { 
       fmt.Println(line) 
      } 
      fmt.Println() 
     } 

     if err := scn.Err(); err != nil { 
      fmt.Fprintln(os.Stderr, err) 
      break 
     } 
     if len(lines) == 0 { 
      break 
     } 
    } 
} 

консоли:

 
Enter Lines: 
Hello 
World 
^] 

Result: 
Hello 
World 

Enter Lines: 
Farewell 

World 

^] 

Result: 
Farewell 

World 


Enter Lines: 
^] 

Чтобы прекратить набор линий, на пустой строке введите: < ctrl+ <]>Enter>. Для завершения ввода введите одну строку: < ctrl+]> < Enter>.

+0

Это не работает, когда я пытаюсь вставить многострочный текст с пустой строкой между словами из буфера обмена. –

+0

@MaximYefremov: Он делает сейчас. См. Мой пересмотренный ответ. – peterSO

0

Посмотрите на документацию для bufio.ReadString, в которой указано, что персонаж, который вы передадите ему, заставит функцию прекратить чтение и возврат. Если вы хотите принять многострочный ввод, вам нужно придумать какую-либо схему для дифференцирования строк новой строки ('\ n'), которые продолжат утверждение, и все, что завершает заявление.

Редактировать: Вот неплохой быстрый хакерский пример, который расширяет ваш код для распознавания многострочного ввода. Он делает это, определяя «завершение» оператора как пустую строку, содержащую только «\ n». Вы можете видеть, что это просто буферизация нескольких чтений в один «блок». Вы можете стать более умными и читать клавиатуру напрямую, но независимо от того, что вам нужно будет определить какую-то схему, которую вы можете программно распознать как многолинейную или одиночную.

package main 

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

func main() { 
    cnt := false 
    var txt []byte 
    for { 
     result := make([]byte, 1024) 
     if cnt == false { 
      fmt.Println("How to read all lines here?") 
     } 
     in := bufio.NewReader(os.Stdin) 
     _, err := in.Read(result) 

     if err != nil { 
      fmt.Println(err) 
     } 
     if result[0] == '\n' { 
      cnt = false 
      fmt.Printf("<----\n%s---->\n", string(txt)) 
      txt = txt[:0] 
     } else { 
      txt = append(txt, result...) 
      cnt = true 
     } 
    } 
} 
0

EOF не может помочь вам, потому что io.EOF имеет тип 'error', но in.ReadString ожидает байт (последовательность '\n' - это байт). Но в любом случае, если я понимаю ваши цели, вам нужно как-то прекратить чтение из stdin. Например, конкретная строка. Как и клиент mysql, «exit;» строка, чтобы завершить сеанс.

Посмотрите на линии сканирования, например http://golang.org/pkg/bufio/#example_Scanner_lines и улучшить его замена

fmt.Println(scanner.Text()) // Println will add back the final '\n' 

что-то вроде:

allInput += scanner.Text() + "\n" 
if scanner.Text() == "exit;" { 
    //your actions on exit... 
    //...  
    fmt.Println("Exiting. By") 
    return 
} 

Или, если вы хотите программировать на работу в трубах и принять многострочный ввод из другого выхода программы вы можете использовать io.ReadFull или PipeReader функции

Смежные вопросы