From: WATANABE Tetsuya Date: 1998-02-24T09:26:14+09:00 Subject: [ruby-list:6676] head.rb すごい単純な例なのですが、$<.close の効果に気がつかなくて... ■ Ruby で head(1) Ruby で UNIX の基本ツールの一つ head(1) を作ってみました。 ファイルを扱う際の基本パターンですので、小さいですが基本パ ターン? になっているように思います。 ■ ファイルを扱う基本パターン ファイルを表示するだけの cat(1) との同等品は、Ruby ではつ ぎのように書きます。 ------------------------------ #! /usr/local/bin/ruby # Created: February 21,1998 Saturday 18:41:43 while gets print end exit ------------------------------ gets は、便利な機能を持っています。gets は一行読み込んで きます。引数がなければ「$<」(ARGV) でアクセスできる仮想的 なファイルから読み込みます。これは、コマンドライン上で指 定した一連の「ファイル」または、標準入力になります。Perl では ------------------------------ while (<>) { # 一行が $_ に入力される } ------------------------------ でよく処理するものです。 ■ $. と $< ちょっと悩んだのが、$. の扱いです。Perl と同様に $. は、 「最後に読んだ入力ファイルの行番号」と定義されています。 head(1) の処理場合、必要行数を表示したら次のファイルの処 理を行います。このときの方法がよく分かりませんでした。マ ニュアルやサンプルを参照してみたのですが... Perl では、現在扱っているファイルを明示的に close するこ とで、すべてがうまく行きます。$. をリセットします。きっと Ruby でも同様の方法があると思い確認した結果が次のソースコー ドにある方法です。$<.close を実施することで、Perl とまっ たく同じに現在の扱っているファイルがクローズされます。そ して $. で示される行番号もリセットされます。 実はこれに気がつくまで $<.file.close とやっていて失敗して いました。ちょっと気がつかなくて... ■ ソースコード ------------------------------ #! /usr/local/bin/ruby # Created: February 22,1998 Sunday 09:30:21 # Author: tetsu(WATANABE Tetsuya) def usage STDERR.print "usage: #$0 [-number] [files ...]\n" exit 1 end lines = 10 while $_ = ARGV[0] and /^-/ ARGV.shift if /^-(\d+)$/; lines = Integer($1); next end usage end while gets print '==> ', $<.filename, " <==\n" if $. == 1 if $. > lines $<.close else print end end exit ------------------------------ 次のソースコードは便利な方法を使わず、ほとんどを C のプロ グラムと同じレベルで記述しているものです。どちらもやって いることは同等なのですが... ------------------------------ #! /usr/local/bin/ruby # Created: February 21,1998 Saturday 18:23:42 # Author: tetsu(WATANABE Tetsuya) def usage STDERR.print "usage: #$0 [-number] [files ...]\n" exit 1 end lines = 10 while $_ = ARGV[0] and /^-/ ARGV.shift if /^-(\d+)$/; lines = Integer($1); next end usage end n = ARGV.length if n == 0 while gets print break if $. >= lines end else while file = ARGV.shift print "==> #{file} <==\n" if n > 1 f = File.open(file) while f.gets print break if $. >= lines end f.close end end exit ------------------------------ -- WATANABE Tetsuya HP Japan PSO e-mail tetsu@jpn.hp.com