看了this个问题后,我有以下代码:
$/ = "\0"
answer = STDIN.gets
现在,我希望这会让用户:
然而,我实际看到的行为是:
那么,为什么单行情况(即如果用户输入了一些文本但没有换行,然后点击 Ctrl-D )则需要两次按 Ctrl-D ?如果用户什么都不输入,为什么它会起作用呢? (我已经注意到,如果他们没有输入任何内容并点击 Ctrl-D ,我没有得到一个空字符串但是nil类 - 我试图在结果上调用.empty?
时发现了这个,因为它突然失败了。如果有办法让它返回一个空字符串,那就太好了。我更喜欢检查.empty?
到==
,并不特别想要为nil类定义.empty?
。)
编辑:由于我真的想知道在Ruby中执行此操作的“正确方法”,我将提供200个代表的赏金。我也会接受一些答案,这些答案可以通过合理的“提交”程序进入终端多行输入 - 我将成为'合适'的判断者。例如,我们目前正在使用两个“\ n”,但这不合适,因为它会阻止段落并且不直观。
答案 0 :(得分:2)
从终端设备读取STDIN时,您正在以稍微不同的模式从文件或管道读取STDIN。
当从tty Control-D(EOF)读取时,如果输入缓冲区为空,则只发送EOF。如果它不为空,则将数据返回到读取系统调用,但不发送EOF。
解决方案是使用一些较低级别的IO并一次读取一个字符。以下代码(或类似的东西)将执行您想要的操作
#!/usr/bin/env ruby
answer = ""
while true
begin
input = STDIN.sysread(1)
answer += input
rescue EOFError
break
end
end
puts "|#{answer.class}|#{answer}|"
使用各种输入运行此代码的结果如下: -
INPUT 这是一行< CR>< Ctrl-D>
|String|This is a line |
INPUT 这是一行< Ctrl-D>
|String|This is a line|
<强> INPUT 强>&LT;按Ctrl-d取代;
|String||
答案 1 :(得分:2)
基本问题是终端本身。查看帖子右侧的许多相关链接。要解决这个问题,您需要将终端置于原始状态。以下在Solaris机器上为我工作:
#!/usr/bin/env ruby
# store the old stty settings
old_stty = `stty -g`
# Set up the terminal in non-canonical mode input processing
# This causes the terminal to process one character at a time
system "stty -icanon min 1 time 0 -isig"
answer = ""
while true
char = STDIN.getc
break if char == ?\C-d # break on Ctrl-d
answer += char.chr
end
system "stty #{old_stty}" # restore stty settings
answer
我不确定是否需要存储和恢复stty设置,但我已经看到其他人这样做了。