318

Ruby でコマンドライン入力を処理したい:

> cat input.txt | myprog.rb
> myprog.rb < input.txt
> myprog.rb arg1 arg2 arg3 ...

それを行う最良の方法は何ですか?特に、空白の STDIN を扱いたいと考えており、エレガントなソリューションを期待しています。

#!/usr/bin/env ruby

STDIN.read.split("\n").each do |a|
   puts a
end

ARGV.each do |b|
    puts b
end
4

10 に答える 10

416

以下は、あいまいなRubyのコレクションで見つけたものです。

したがって、Ruby では、Unix コマンドのシンプルなノーベル実装は次のcatようになります。

#!/usr/bin/env ruby
puts ARGF.read

ARGF入力に関してはあなたの友達です。これは、名前付きファイルからすべての入力を取得するか、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

ありがたいことに、Ruby ではダイヤモンド演算子を取得できませんでしたがARGF、代替として取得できました。あいまいですが、実際には便利です。-iコマンドラインで言及されたすべてのファイルに著作権ヘッダーをインプレースで追加するこのプログラムを考えてみましょう (別の Perlism のおかげです):

#!/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.
#++

クレジット:

于 2008-11-07T22:29:13.043 に答える
44

Ruby は、STDIN を処理する別の方法を提供します: -n フラグです。プログラム全体を STDIN のループ内にあるものとして扱います (コマンド ライン引数として渡されたファイルを含む)。たとえば、次の 1 行のスクリプトを参照してください。

#!/usr/bin/env ruby -n

#example.rb

puts "hello: #{$_}" #prepend 'hello:' to each line from STDIN

#these will all work:
# ./example.rb < input.txt
# cat input.txt | ./example.rb
# ./example.rb input.txt
于 2011-03-03T03:13:07.673 に答える
33

何が必要かよくわかりませんが、次のようなものを使用します。

#!/usr/bin/env ruby

until ARGV.empty? do
  puts "From arguments: #{ARGV.shift}"
end

while a = gets
  puts "From stdin: #{a}"
end

ARGV 配列は first の前は空であるためgets、Ruby は引数を読み取り元のテキスト ファイルとして解釈しようとしないことに注意してください (動作は Perl から継承されています)。

stdin が空の場合、または引数がない場合、何も出力されません。

いくつかのテストケース:

$ 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!
于 2008-11-07T19:51:40.020 に答える
19

もしかしてこういうこと?

#/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

例:

> 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
于 2008-11-07T20:53:14.127 に答える
13
while STDIN.gets
  puts $_
end

while ARGF.gets
  puts $_
end

これは Perl にインスパイアされています:

while(<STDIN>){
  print "$_\n"
}
于 2012-07-09T21:52:58.373 に答える
4

素早く簡単:

STDIN.gets.chomp == 'YES'

于 2016-11-11T12:00:50.837 に答える
1

パラメータで使用するには、呼び出す前ARGFにクリアする必要があることを追加します。これは、ファイル名として何かを扱い、最初にそこから行を読み取るためです。ARGVARGF.eachARGFARGV

「tee」の実装例を次に示します。

File.open(ARGV[0], 'w') do |file|
  ARGV.clear

  ARGF.each do |line|
    puts line
    file.write(line)
  end
end
于 2016-01-20T17:15:32.050 に答える
1

私はこのようなことをします:

all_lines = ""
ARGV.each do |line|
  all_lines << line + "\n"
end
puts all_lines
于 2016-03-31T10:19:40.317 に答える
0

ほとんどの回答は、引数が標準入力に分類されるコンテンツを含むファイル名であると想定しているようです。以下はすべて単なる引数として扱われます。STDIN が TTY からのものである場合、それは無視されます。

$ cat tstarg.rb

while a=(ARGV.shift or (!STDIN.tty? and STDIN.gets) )
  puts a
end

引数または stdin は、空にすることも、データを含めることもできます。

$ cat numbers 
1
2
3
4
5
$ ./tstarg.rb a b c < numbers
a
b
c
1
2
3
4
5
于 2016-10-12T13:01:00.520 に答える