Странно поведение при промяна на разделителя на реда и след това обратно

Следвах съвета от този въпрос, когато опитвах за четене на многоредов вход от командния ред:

# change line separator
$/ = 'END'
answer = gets
pp answer

Получавам обаче странно поведение от STDIN#gets, когато се опитвам да променя $/ обратно:

# put it back to normal
$/ = "\n"
answer = gets
pp answer
pp 'magic'

Това създава резултат като този, когато се изпълнява с Ruby:

$ ruby multiline_input_test.rb
this is
        a multiline
  awesome input string
                        FTW!!
END
"this is\n\ta multiline\n  awesome input string\n            \t\tFTW!!\t\nEND"
"\n"
"magic"

(Въвеждам до END и останалото се извежда от програмата, след което програмата излиза.)

Не спира, за да получи вход от потребителя, след като променя $/ обратно на "\n". Така че въпросът ми е прост: защо?

Като част от по-голямо (но все още малко) приложение се опитвам да измисля начин за записване на бележки; както е, това странно поведение е потенциално опустошително, тъй като останалата част от програмата ми няма да може да функционира правилно, ако не мога да нулирам разделителя на редовете. Опитах всякакъв начин да използвам двойни и единични кавички, но това не изглежда да е проблемът. Някакви идеи?


person Daniel Brady    schedule 05.07.2013    source източник
comment
Вашето описание в последния кодов блок не е ясно. Коя част е кодът, коя част е въвеждането от потребителя и коя част е отговорът?   -  person sawa    schedule 05.07.2013
comment
@sawa Съжалявам за това. Кодовите фрагменти, които предоставих, са целият код, който изпълнявам в „multiline_input_test.rb“. Когато това се изпълни, то спира, чакайки въвеждане от потребителя. Въведох това е многоредов страхотен входен низ FTW!! (с произволен празен интервал), след което напишете „КРАЙ“. Останалото е това, което беше отпечатано: няма друга пауза при изпълнение на второто gets от моя код.   -  person Daniel Brady    schedule 05.07.2013
comment
изглежда, че вторият gets просто връща нов ред, който никога не съм въвеждал   -  person Daniel Brady    schedule 05.07.2013


Отговори (1)


Проблемът, който имате, е, че въведеното ви завършва с END\n. Ruby вижда END и все още има \n в буфера. Вие направяте успешно задаване на разделителя на входния запис обратно на \n, така че този знак незабавно да се консумира от втория gets.

Следователно имате две лесни възможности:

  1. Задайте разделителя на входния запис на END\n (използвайте двойни кавички, за да работи символът за нов ред):

    $/ = "END\n"
    
  2. Изчистете буфера с допълнително извикване на gets:

    $/ = 'END'
    answer = gets
    gets # Consume extra `\n`
    

Смятам, че вариант 1 е по-ясен.

Това показва, че работи на моята система, използвайки опция 1:

$ ruby multiline_input_test.rb 
this is
        a multiline
  awesome input string
                        FTW!!
END
"this is\n        a multiline\n  awesome input string\n                        FTW!!\nEND\n"
test
"test\n"
"magic"
person Darshan Rivka Whittle    schedule 05.07.2013
comment
Аааа, благодаря ти! Вярвам, че ми спестихте много минути отстраняване на грешки. Това е напълно логично, вече мислех нещо от рода на промиване на буфера, но аз също харесвам първия ви вариант като по-добра алтернатива. - person Daniel Brady; 05.07.2013
comment
Благодаря за редакциите на въпроса ми, btw :) яснотата винаги е важна. - person Daniel Brady; 05.07.2013