本文翻译自:Best practices with STDIN in Ruby?
I want to deal with the command line input in Ruby: 我想处理Ruby中的命令行输入:
> cat input.txt | myprog.rb
> myprog.rb < input.txt
> myprog.rb arg1 arg2 arg3 ...
What is the best way to do it? 最好的方法是什么? In particular I want to deal with blank STDIN, and I hope for an elegant solution. 特别是我想处理空白STDIN,我希望有一个优雅的解决方案。
#!/usr/bin/env ruby
STDIN.read.split("\n").each do |a|
puts a
end
ARGV.each do |b|
puts b
end
#1楼
参考:https://stackoom.com/question/195S/Ruby中STDIN的最佳实践
#2楼
while STDIN.gets
puts $_
end
while ARGF.gets
puts $_
end
This is inspired by Perl: 这是受Perl的启发:
while(<STDIN>){
print "$_\n"
}
#3楼
I am not quite sure what you need, but I would use something like this: 我不太确定你需要什么,但我会用这样的东西:
#!/usr/bin/env ruby
until ARGV.empty? do
puts "From arguments: #{ARGV.shift}"
end
while a = gets
puts "From stdin: #{a}"
end
Note that because ARGV array is empty before first gets
, Ruby won't try to interpret argument as text file from which to read (behaviour inherited from Perl). 请注意,因为ARGV数组在第一次gets
之前是空的,所以Ruby不会尝试将参数解释为从中读取的文本文件(从Perl继承的行为)。
If stdin is empty or there is no arguments, nothing is printed. 如果stdin为空或没有参数,则不打印任何内容。
Few test cases: 几个测试用例:
$ cat input.txt | ./myprog.rb
From stdin: line 1
From stdin: line 2
$ ./myprog.rb arg1 arg2 arg3
From arguments: arg1
From arguments: arg2
From arguments: arg3
hi!
From stdin: hi!
#4楼
Something like this perhaps? 也许这样的事情?
#/usr/bin/env ruby
if $stdin.tty?
ARGV.each do |file|
puts "do something with this file: #{file}"
end
else
$stdin.each_line do |line|
puts "do something with this line: #{line}"
end
end
Example: 例:
> cat input.txt | ./myprog.rb
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb < input.txt
do something with this line: this
do something with this line: is
do something with this line: a
do something with this line: test
> ./myprog.rb arg1 arg2 arg3
do something with this file: arg1
do something with this file: arg2
do something with this file: arg3
#5楼
Following are some things I found in my collection of obscure Ruby. 以下是我在晦涩的Ruby系列中发现的一些东西。
So, in Ruby, a simple no-bells implementation of the Unix command cat
would be: 所以,在Ruby中,Unix命令cat
一个简单的no-bells实现将是:
#!/usr/bin/env ruby
puts ARGF.read
ARGF
is your friend when it comes to input; 在输入方面, ARGF
是你的朋友; it is a virtual file that gets all input from named files or all from STDIN. 它是一个虚拟文件,从命名文件或STDIN中获取所有输入。
ARGF.each_with_index do |line, idx|
print ARGF.filename, ":", idx, ";", line
end
# print all the lines in every file passed via command line that contains login
ARGF.each do |line|
puts line if line =~ /login/
end
Thank goodness we didn't get the diamond operator in Ruby, but we did get ARGF
as a replacement. 谢天谢地,我们没有得到Ruby中的钻石操作符,但我们确实将ARGF
作为替代品。 Though obscure, it actually turns out to be useful. 虽然模糊不清,但它实际上证明是有用的。 Consider this program, which prepends copyright headers in-place (thanks to another Perlism, -i
) to every file mentioned on the command-line: 考虑一下这个程序,该程序在命令行中提到的每个文件上就地存在版权标题(感谢另一个Perlism, -i
):
#!/usr/bin/env ruby -i
Header = DATA.read
ARGF.each_line do |e|
puts Header if ARGF.pos - e.length == 0
puts e
end
__END__
#--
# Copyright (C) 2007 Fancypants, Inc.
#++
Credit to: 归功于:
- http://www.oreillynet.com/ruby/blog/2007/04/trivial_scripting_with_ruby.html#comment-565558 http://www.oreillynet.com/ruby/blog/2007/04/trivial_scripting_with_ruby.html#comment-565558
- http://blog.nicksieger.com/articles/2007/10/06/obscure-and-ugly-perlisms-in-ruby http://blog.nicksieger.com/articles/2007/10/06/obscure-and-ugly-perlisms-in-ruby
#6楼
I'll add that in order to use ARGF
with parameters, you need to clear ARGV
before calling ARGF.each
. 我要补充一点,为了使用带有参数的ARGF
,你需要在调用ARGF.each
之前清除ARGV
。 This is because ARGF
will treat anything in ARGV
as a filename and read lines from there first. 这是因为ARGF
会将ARGV
中的任何内容视为文件名并首先从那里读取行。
Here's an example 'tee' implementation: 这是一个'tee'实现示例:
File.open(ARGV[0], 'w') do |file|
ARGV.clear
ARGF.each do |line|
puts line
file.write(line)
end
end