如何在Ruby中检查ARGF是否为空

10

我想像这样处理 ARGF

# file.rb
if ARGF.???
  puts ARGF.read
else
  puts "no redirect."
end

$ echo "Hello world" | ruby file.rb
Hello world

$ ruby file.rb
no redirect.

我需要在不等待用户输入的情况下执行操作。我尝试过使用eof?closed?,但没有帮助。有什么想法吗?

注意:我误解了ARGF。请参见下面的评论。

3个回答

7

基本上,你需要检查 #filename。一种方法是:

if ARGF.filename != "-"
  puts ARGF.read
else
  puts "no redirect."
end

这是更完整的形式:

#!/usr/bin/env ruby
if ARGF.filename != "-" or (not STDIN.tty? and not STDIN.closed?)
  puts ARGF.read
else
  puts "No redirect."
end

另一个:

#!/usr/bin/env ruby
if not STDIN.tty? and not STDIN.closed?
  puts STDIN.read
else
  puts "No redirect."
end

echo "Hello World" | ruby file.rb 将返回 filename - - fl00r
@fl00r 除了检查ARGF外,您还需要检查stdin是否为终端输入。请参见更新。 - konsolebox
foo 真的存在吗?您是否也想检查它是否存在并避免在不存在时进行读取? - konsolebox
1
@MarcJ 你可能需要自己清除ARGV中不存在的文件。似乎filename只给出第一个文件的名称,所以如果输入是ruby file.rb existing.txt non-existing.txt,使用它就没有什么用了。你可以在使用ARGF之前做一些像这样的事情:ARGV.select! { |file| File.exists?(file) },并处理其他参数,只留下指向现有文件的参数。 - Daniël Knippers
1
如果将ARGF作为ARGV [0]传递,则第三个返回值为“false”。 - Nakilon
显示剩余3条评论

1

也许有更好的方法,但对于我来说,我需要读取作为参数传递的文件的内容,同时也需要将文件的内容重定向到标准输入。

my_executable

#!/usr/bin/env ruby
puts ARGF.pos.zero?

那么

$ my_executable file1.txt   # passed as argument
#=> true
$ my_executable < file1.txt # redirected to stdin
#=> true
$ my_executable
#=> false

$ echo "123" | ruby -e "p ARGF.pos" -> -e:1:in 'pos': Illegal seek @ rb_io_tell - <STDIN> (Errno::ESPIPE) - Nakilon

0

因此,我采用了目前提供的三种解决方案:

p (not STDIN.tty? and not STDIN.closed?)
p ARGF.filename
p ARGF.pos

然后发现它们都不起作用:

$ ruby temp.rb 
false
"-"
36471287

$ ruby temp.rb temp.rb 
false
"temp.rb"
0

$ echo 123 | ruby temp.rb 
true
"-"
temp.rb:3:in `pos': Illegal seek @ rb_io_tell - <STDIN> (Errno::ESPIPE)
        from temp.rb:3:in `<main>'

因为假设能够调用ARGF.read,你想要得到false/true/true。

所以我认为你需要将它们结合起来:

!STDIN.tty? && !STDIN.closed? || ARGF.filename != ?-

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接