Rubyのワンライナー上でのスクリプトについて質問です。


ファイルfoo.txtのn行目からm行目までを表示するワンライナーで、

 $ cat foo.txt | ruby -ne 'print if n..m'

という書き方をよく目にします。

このワンライナー中でRubyの実行スクリプトの部分は、
省略せずに書くと、どのようになるのでしょうか?

特に範囲オブジェクトが、何に作用しているのかがわかりません。

ファイルfoo.txtのなかで正規表現にマッチする行を表示するワンライナー

 $ cat foo.txt | ruby -ne 'print if /bar/'

は、

while gets()
 print $_ if $_ =~ /bar/
end

だと思うのですが、
できればこのような形で示していただけると助かります。


初歩的な質問で申し訳ありませんが、よろしくお願いします。

回答の条件
  • 1人2回まで
  • 登録:2008/07/31 14:54:35
  • 終了:2008/08/01 16:44:52

回答(3件)

id:rubikitch No.1

るびきち回答回数120ベストアンサー獲得回数222008/07/31 18:56:24

ポイント30pt

ん、実行しても素通りするだけですが?

$ wc -l ~/.emacs
200 /m/home/rubikitch/.emacs
$ cat ~/.emacs | ruby -ne 'print if 2..4' | wc -l
200
id:kanouk

Rubyのバージョンが結構古かった(1.8.1)のですが、

そのへんも影響しているのでしょうか。

手元の環境では、以下のようにできました。

[kanouk@rhel ~]$ ruby -v

ruby 1.8.1 (2003-12-25) [i386-linux-gnu]

[kanouk@rhel ~]$ cat .cshrc | wc -l

32

[kanouk@rhel ~]$ cat .cshrc | ruby -ne 'print if 2..5' | wc -l

4

違う環境(1.8.6)で試してみたら、

おっしゃる通り素通りしました。

2008/08/01 11:10:48
id:komamitsu No.2

komamitsu回答回数21ベストアンサー獲得回数22008/08/01 01:27:30

ポイント30pt

> $ cat foo.txt | ruby -ne 'print if n..m'

Perlだとそのまんまでいけますけど、

Rubyの場合、確かにそのままじゃいかんすねぇ(いけるバージョンあるのかなぁ)。

komamitsu@onion:~/caml$ wc -l tree.ml

13 tree.ml

komamitsu@onion:~/caml$ cat tree.ml | perl -ne 'print if 2..4' | wc -l

3

komamitsu@onion:~/caml$ cat tree.ml | ruby -ne 'print if 2..4' | wc -l

13

特殊変数 $. の値を比較してあげればいいから、適当にこう?

komamitsu@onion:~/caml$ cat tree.ml | ruby -ne 'print if (2..4).include? $.' | wc -l

3

ちなみに、Perlのほうは、

暗黙的に $. との比較を行っている、みたいな。

id:Bookmarker No.3

しおり回答回数191ベストアンサー獲得回数342008/08/01 01:38:01

ポイント30pt

何か抜けてませんか?

こんなのならわかりますが。

$ cat foo.txt | ruby -ne 'print if ($.==2)..($.==4)'
line 2
line 3
line 4

範囲式 - 条件式としての範囲式:

条件式として範囲式が用いられた場合には、状態を持つ sed や awk 由来の特殊な条件式として振る舞います。

「..」の場合:

  1. 初期状態では式1だけを評価し、式1が真を返すまでは false を返します。
  2. 式1が真を返すと true を返します。式2が真なら初期状態に戻ります。
  3. この後は式2だけを評価し、式2が真を返すまで true を返します。
  4. 式2が真を返すと true を返したあと、初期状態に戻ります。
  • id:quintia
    ソースを書き写す時に何かを間違えていたか抜け落ちたかしていると思います。
    「正しく動くソース」か、元々のサンプルが書いてあるURLの情報が欲しいですね。
  • id:kanouk
    新しいRubyのバージョンでは再現しなかったので、
    (なぜ1.8.1ではOKだったのか多少モヤモヤしますが)
    これでクローズとさせていただきます。

    みなさま、回答ありがとうございました。
  • id:Bookmarker
    > (なぜ1.8.1ではOKだったのか多少モヤモヤしますが)

    1.8.1 では、
    if 整数リテラル..整数リテラル

    if ($.==整数リテラル)..($.==整数リテラル)
    と同じ意味だったようです。

    1.8.3 から動作が変わっているようですが、仕様変更したという話は見当たりませんでした。
    もしかしたらバグかもしれませんが、「なくしたい」って言ってたようなので、こっそりなくしたのかも:-)

    Subject: [ruby-dev:11773] Re: [PATCH & Q] literal in condition
    http://blade.nagaokaut.ac.jp/cgi-bin/vframe.rb/ruby/ruby-dev/11758?11732-12298
  • id:Bookmarker
    バグだったようで、昨日修正されました。

    Ruby 1.8 - Bug #387: if 整数リテラル..整数リテラル ≠ if ($.==整数リテラル)..($.==整数リテラル) - Ruby Issue Tracking System:
    http://redmine.ruby-lang.org/issues/show/387

    ruby-cvs:25575:
    >http://www.atdot.net/~ko1/w3ml/w3ml.cgi/ruby-cvs/msg/25575>
    fix up fixnum range literal in conditional as automagical line number comparison. [ruby-core:12124], [ruby-dev:35731]
    <<

    >||
    % ./ruby -vne 'print if 2..4' foo.txt
    ruby 1.8.7 (2008-08-04 revision 0) [i386-freebsd7.0]
    line 2
    line 3
    line 4
    ||<

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません