293


115

Rubyのコマンドライン入力を扱いたい。

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

最善の方法は何ですか? 特に私は空白のSTDINを扱いたいと思います、そして私は優雅な解決策を望みます。

#!/ usr / bin / env ruby

STDIN.read.split( "\ n")。それぞれが| a |終わらせる

ARGV.each do | b | b末尾に置く

9 Answer


387


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

そのため、Rubyでは、Unixコマンド `cat`の単純な無鐘型実装は次のようになります。

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

http://ruby-doc.org/core-2.4.0/ARGF.html [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`を手に入れました。 あいまいですが、実際には有用であることがわかりました。 このプログラムを考えてみてください。このプログラムは、コマンドラインで言及されているすべてのファイルの代わりに(別の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.
#++

クレジット:


40


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

#!/ usr / bin / env ruby​​ -n

#example.rb

STDINの各行に "hello:#{$ _}" #prepend 'hello:'を追加します。

#これらはすべてうまくいくでしょう:#./example.rb <input.txt#cat input.txt | ./example.rb#./example.rb input.txt


31


私はあなたが何を必要としているのかよくわかりませんが、私はこのようなものを使うでしょう:

#!/usr/bin/env ruby

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

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

ARGV配列は最初の `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!


17


おそらくこのようなもの?

#/ usr / bin / env ruby

$ stdin.ttyの場合 ARGV.each do | file | "このファイルを使って何かをします。#{file}"を終わらせるには$ stdin.each_line do | line |を使います。 "この行で何かをする:#{line}"を終了

例:

> cat input.txt | ./myprog.rbこの行で何かをする:これはこの行で何かをする:aこの行で何かをする:test> ./myprog.rb <input.txtこの行で何かをする:thisこの行で何かをする:aこの行で何かをする:test> ./myprog.rb arg1 arg2 arg3このファイルで何かをする:arg1このファイルで何かをする:arg2このファイルで何かをする: arg3


11


STDIN.getsが$ _ endを挿入している間

ARGF.getsが$ _ endを挿入している間

これはPerlに触発されています。

while(){print "$ _ \ n"}


1


パラメータと一緒に ARGF`を使うためには、 ARGF.each`を呼び出す前に ARGV`をクリアする必要があります。 これは、 `ARGF`が ARGV`の中の何かをファイル名として扱い、そこから行を最初に読み込むためです。

これが 'tee’実装の例です。

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

  ARGF.each do |line|
    puts line
    file.write(line)
  end
end


1


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

all_lines = "" ARGV.each do | line | all_lines << line "\ n"最後にall_linesを入れます


1


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

$ cat tstarg.rb

a =(ARGV.shiftまたは(!STDIN.tty?) STDIN.gets))が終了します

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

$ cat numbers 1 2 3 4 5 $ ./tstarg.rb a b c <数a b c 1 2 3 4 5


0


早くて簡単:

STDIN.gets.chomp == 'YES'