我想像这样处理 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
。请参见下面的评论。
我想像这样处理 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
。请参见下面的评论。
基本上,你需要检查 #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
也许有更好的方法,但对于我来说,我需要读取作为参数传递的文件的内容,同时也需要将文件的内容重定向到标准输入。
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因此,我采用了目前提供的三种解决方案:
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 != ?-
echo "Hello World" | ruby file.rb
将返回filename -
。 - fl00rfoo
真的存在吗?您是否也想检查它是否存在并避免在不存在时进行读取? - konsoleboxfilename
只给出第一个文件的名称,所以如果输入是ruby file.rb existing.txt non-existing.txt
,使用它就没有什么用了。你可以在使用ARGF
之前做一些像这样的事情:ARGV.select! { |file| File.exists?(file) }
,并处理其他参数,只留下指向现有文件的参数。 - Daniël Knippers