• ベストアンサー

Rubyのスクリプト

つぎのようなスクリプトを組みました。これはこれで、動いておりますが、お願いです。 (1)Rubyらしい書き方にするには、どこを改めればよいですか? (2)ref_file=open("myReference.txt") の部分は、 外部のレファレンスを用いて名前を翻訳しているところです。 この部分を、関数呼び出しでやってしまいたい。どのように組みなおせば良いですか? 宜しくお願いいたします。 --------------------- おおまかな説明:ディレクトリ「myData」の中にあるlogファイルをひとつずつオープン。 まず、「Target」という単語を探し、その直後にある単語を掴んで、外部のレファレンスファイル「myReference.txt」からrealNameを持ってくる。 その後、処理-----を実行する。 myPath='C:\myData\' print Dir.getwd,"\n" Dir.chdir(myPath) Dir.foreach(myPath) { |myFileName| if /.log/i =~myFileName file_source_body=open(myFileName, "r") while text=file_source_body.gets do if(/Target (\w+\/)/=~text) then myTargetName=$1 ref_file=open("myReference.txt") # (2)のアイテムの部分 while ref_info=ref_file.gets do (/#{myTargetName}\s(\S+)/i=~ref_info) && (realName=$1) end ref_file.close end end ------- ------- ------- }

質問者が選んだベストアンサー

  • ベストアンサー
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.5

>誠に申し訳ない。ご指導ください。 うーん、困ったな。 面倒だから「答え」を書いちゃえ。 # 削除されたらゴメンね。 ------ require 'csv' class Reference  # CSV 形式の ref_file を読み込んで、インスタンス変数 @ref_hash に格納  def initialize(ref_file)   @ref_hash = {}   CSV.open(ref_file) do |row|    @ref_hash[row[0]] = row[1]   end  end  # key の辞書引きの結果を返す。辞書になければ nil を返す  def [](key)   @ref_hash[key]  end end ----------------- irb でこんな感じで動くはず irb(main):000:0> ref = Reference.new("Reference.txt") irb(main):001:0> puts ref['aaaa'] => "AAAA" ----------------- クラスっちゅうのは「何か」の抽象化なので、今回は「辞書ファイル」を抽象化して Reference クラスを作成しました。 initialize メソッドは Reference クラスのインスタンスを作成する際の初期化ルーチンで、Reference.new() した時に呼ばれます。今回は "Reference.txt" のようなファイルを引数として、辞書としての自分自身を作成しています。その実体はただのハッシュ。 Ruby では [] 自体もメソッドとして定義できて、その方法は上記の通り、そしてメソッドの呼出し方が通常のメソッドのように foo.bar(baz) ではなくて foo[baz] となります。foo.[](baz) でも呼べるけど見難いだけ。

noname#95859
質問者

お礼

koko_u_さん、ありがとうございます。 教えていただいた、内容で、1点エラーが出ました。 10:in `open': wrong number of arguments (1 for 2) (ArgumentError) CSV.openをハイライトさせて、F1でヘルプを呼び出し、 モード(この場合は、read only ということで 'r')を追加して うまく行きました。 以下をRDEのエディタウィンドウに記述して、実行させました。 --------------------------- require 'csv' class Reference def initialize(ref_file) @ref_hash = {} CSV.open(ref_file,'r') do |row| @ref_hash[row[0]] = row[1] end end def [](key) @ref_hash[key] end end ref = Reference.new("myReference.txt") puts ref['aaaa'] ----------------- CSV.openのところは、下記でもやってみて、OKであることを確認しました。 CSV.foreach(ref_file){|row| @ref_hash[row[0]] = row[1] } ----------------- foo[baz] の, fooとか、barは、ヘルプの中に、よく使われている 言葉なのですね。これも、理解しました。 interactive rubyでの動きも、確認しました。でも、このモードで 丹念に、すべてのステートメントを入力するのは、結構大変ですね。 しかし、このモードは、うまく使えるかもしれないと、思っております。 尚、クラスのことに関しては、難しいです。サブルーチン或いは、関数の代わりにはなっていることは分かりますが、理解するには、時間が必要です。 ありがとうございました。感謝します。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.6

>モード(この場合は、read only ということで 'r')を追加して >うまく行きました。 スマン。適当に回答してるのがバレちゃった。 >CSV.openのところは、下記でもやってみて、OKであることを確認しました。 >CSV.foreach(ref_file){|row| >@ref_hash[row[0]] = row[1] >} 複数行に渡るコードブロックは do ... end で書く方が Ruby っぽいか? >interactive rubyでの動きも、確認しました。でも、このモードで >丹念に、すべてのステートメントを入力するのは、結構大変ですね。 普通に無理です。適当な .rb ファイルを書いて、 irb(main):000:0>load 'foo.rb' でどうぞ。 私は irb はあんまり使ってなくて、xyzzy + ruby-interaction-mode で試しに動かしてみて、問題なければそれをソースにコピペしています。

全文を見る
すると、全ての回答が全文表示されます。
  • notnot
  • ベストアンサー率47% (4856/10272)
回答No.4

IO.foreachと同じにするなら、 io=open(myFileName,"r") begin io.each{|text| text.chomp! print text,"\n" } ensure io.close end また、 text.chomp! print text,"\n" よりは puts text.chomp のほうがRubyらしいと思います。 あと私も単純なケースでは、and や or を多用します。 参考文献ですが、1冊読んだのなら、あとはリファレンスで十分だと思います。http://www.ruby-lang.org/ja/man/

noname#95859
質問者

お礼

notnotさん、ありがとうございます。 よく理解できました。 今後とも、宜しくお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.3

>@ref_hash = {} >この表現で、ハッシュメモリ(3つ)に、入ってくれるものでしょうか? ここは Hash.new してるだけ。 Reference.txt が CSV形式なら手抜きで CSV.open(ref_file) do |row|  @ref_hash[row[0]] = row[1] end とかして下さい。 >(2)このクラスのメッソドとしての def [](key) >メッソドの名称を仮に、nameCnvertとすると、 こっちは完了していて、Reference のメソッド [] を委譲によって定義しているだけです。 ref = Reference.new('Reference.txt') で Reference オブジェクトを作成すれば ref['ほげほげ'] で辞書引きの結果が得られます。

noname#95859
質問者

補足

koko_u_さん、ありがとうございます。 結論から言って、難しい。まだ、理解できていません。 とにかく、動かそうとしています。下記のように、cut&tryしました。 -------------myReference.txtの内容----------- aaaa,AAAA bbbb,BBBB cccc,CCCC -------------Ruby script trial--------------- myPath='D:\MyFolder\Study_Programming\hash' print Dir.getwd,"\n" Dir.chdir(myPath) class Reference ref_fil="myReference.txt" def initialize(ref_file) @ref_hash = {} end def [](key) CSV.open(ref_file) do |row| @ref_hash[row[0]] = row[1] end end end ref = Reference.new('Reference.txt') print ref['aaaa'],"\n" ------------------------------------------ 実行結果です ------------------------------------------ D:/MyFolder/Study_Programming/hash D:/MyFolder/Study_Programming/hash/rb25E.tmp:12:in `[]': uninitialized constant Reference::CSV (NameError) from D:/MyFolder/Study_Programming/hash/rb25E.tmp:19 Completed(1) ------------------------------------------ 誠に申し訳ない。ご指導ください。

全文を見る
すると、全ての回答が全文表示されます。
  • notnot
  • ベストアンサー率47% (4856/10272)
回答No.2

ファイルから1行ずつ読んで処理するなら、 file_source_body=open(myFileName, "r") while text=file_source_body.gets do じゃなくて、 IO.foreach(myFileName) do |text| ですかね。明示的にcloseしないといけない書き方は避けられるなら避けるほうがいいです。closeするなら、begin ~ ensure ~ end を使う。 (/#{myTargetName}\s(\S+)/i=~ref_info) && (realName=$1) は、その上と同じパターンで if のほうがいいと思うけど、if を使わないなら、優先度の低い and を使って、 /#{myTargetName}\s(\S+)/i=~ref_info and realName=$1

noname#95859
質問者

お礼

notnotさん、ありがとうございます。 下記の2つのスクリプトは、同じであることを、理解しました。 小生の持っている本(たのしいRuby 第2版、Rubyではじめる気軽なプログラミング) には、IO.foreach(myFileName){|text|・・・・は書かれていないと思います。 他に、本を買うとしたら、どの本が良いでしょうか? ------------------------ myFileName="test.csv" IO.foreach(myFileName){|text| text.chomp! print text,"\n" } ------------------------- io=open(myFileName,"r") io.each{|text| text.chomp! print text,"\n" } ------------------------- (2)(/#{myTargetName}\s(\S+)/i=~ref_info) && (realName=$1) に関しては、Perlで、覚えたやり方で、Rubyでも通用することを理解し、 やはり、これからも使ってしまうと思います。 && (andでも構いませんが)で、いくつもつなぐ事で、見た目は良くないですが、 複雑な条件が、1行で記述できて、結構、スクリプトがすっきりしてしまいます。

全文を見る
すると、全ての回答が全文表示されます。
  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

>Rubyらしい書き方にするには、どこを改めればよいですか? さぁ? open を差し替えたいなら、IO.foreach(path) { |line| ... } を使うくらいしか。 >関数呼び出しでやってしまいたい。どのように組みなおせば良いですか? 単純なところでは class Reference  def initialize(ref_file)   @ref_hash = {}   ...  end  def [](key)   @ref_hash[key]  end end みたいなのをデッチ上げて、最初に myReference.txt をまるごと読み込む。

noname#95859
質問者

補足

名前を変換するのを、ハッシュメモリを使ってやってしまうというのは、 「なるほど!!!」、感心しました。今まで、ハッシュと言うものは聞いた ことがありましたが、こういうふうに使えるとは、知りませんでした。 本を買ってきて、Classを読んでおります。 今一、理解しづらいところです。 class Reference  def initialize(ref_file)   @ref_hash = {}   ...  end  def [](key)   @ref_hash[key]  end end ------- (1)仮に、myReference.txt が次のようなファイルであるとして、 aaaa,AAAA bbbb,BBBB cccc,CCCC --------- @ref_hash = {} この表現で、ハッシュメモリ(3つ)に、入ってくれるものでしょうか? (確認しようとして、やってはいるのですが、如何せん、呼び出し方がまだ、分からず・・・ (2)このクラスのメッソドとしての def [](key) メッソドの名称を仮に、nameCnvertとすると、 def nameCnvert(key) @ref_hash[key] end これで、良いでしょうか? (3)このメッソドの呼び出し方は? nameCnvertは、メッソドであるゆえ、オブジェクトが必要・・・しかし、 何を持ってくればよいのか? 大変申し訳ない。宜しくお願いいたします。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Rubyにおける変数

    Windows2000上で、Rubyを動かしています。 皆様のお陰で、少しずつ進んでおります。しかし、また質問させてください。 変数に、ファイル名を代入して、実行すると、動かなくなりました。 実名を入れた、system('tar zxf test_20070511.tar.gz')では、動きますが、 変数にした、system('tar zxf myFilename')では、動きません。 Rubyスクリプト ---------------------- print Dir.getwd,"\n" Dir.chdir('C:\myData\myData2') print Dir.getwd,"\n" dir = Dir.open('C:\myData\myData2') while myFilename=dir.read do if /.tar.gz/i =~myFilename then puts myFilename system('tar zxf myFilename') end end dir.close ------------------------------------ 宜しくお願いいたします。

  • Ruby ファイル出力について

    あるファイルを一行づつ処理したものを、別のbuta.txtというファイルに書き出したいのですが、どうも上手くできません・・・。 誰か助けてください。お願いします。 ■かけるデータの内容■ banana banana ■プログラム■ file_name = ARGV.shift i = open(file_name) z = open("buta.txt", "w") while line = i.gets line.gsub(/a/, "A") line.sub(/a/, "A") ※ここに何かいれる?? end ■buta.txtの内容■ bAnAnA bAnana         になったらいいのですが。

  • ファイル名の一括置換がIF文のときだけエラーになる

    ファイル名の一括置換がIF文のときだけエラーになる こんにちは。VBA初心者です。 フォームから受け取ったディレクトリ内にあるファイルの名前を一括置換しようとして、以下のようなコードを書いたのですが、「実行時エラー'53' ファイルがありません。」となってしまします(だだし、1つ目のファイルだけは正しくリネームされます)。 フォームから受け取ったパスは使用せず(IF文は使用せず)、例えば、ファイル名の末尾を「_ja.txt」から「_de.txt」と固定的に置換するだけならちゃんと動くのですが、どこがいけないでしょうか。 ※VBEのローカルペインによると、エラー時の「myRename1」には「"D:\export\de\test_ja.txt"」、「myRename2」には「"D:\export\de\acn200_de.txt"」が格納されているので、問題ないように思えるのですが。。。 Sub ファイル名変更(myPath As String) Dim myFilename1 As String Dim myFilename2 As String Dim myRename1 As String Dim myRename2 As String myPath = myPath & "\" myFilename1 = Dir(myPath & "*_ja.txt") If myPath = "D:\export\de\" Then myFilename2 = Replace(myFilename1, "_ja.txt", "_de.txt") ElseIf myPath = "D:\export\en\" Then myFilename2 = Replace(myFilename1, "_ja.txt", "_en.txt") Else myFilename2 = Replace(myFilename1, "_ja.txt", "_fr.txt") End If myRename1 = myPath & myFilename1 myRename2 = myPath & myFilename2   Do While myFilename1 <> "" Name myRename1 As myRename2 Loop End Sub

  • Excelでの Dir

    excel VBAにて Dir関数を用いて、フォルダに存在するファイルを つかむのに、下記のスクリプトがあります。(渡辺ひかる氏のサンプル集)。 質問は、このスクリプトで引っ張り出されるファイルの順番です。本を色々調べたのですが、順番は、「不明」とあります。 しかし、現実は、アルファベット順? に並んでいるように思われます。 本当のところは、どうなんでしょう? 「不明」なのか、それとも「順番が成立している」のか? よろしくお願いします。 ---------------------------------------- Option Explicit Sub P_Sample003() Dim myPath As String Dim myFileName As String Dim i As Long myPath = ThisWorkbook.Path & "\" '任意のフォルダ myFileName = Dir(myPath, 0) Do While Len(myFileName) > 0 Debug.Print myPath & myFileName myFileName = Dir() Loop End Sub

  • readdirでのファイル名取得

    readdir()にて、textファイルのみ取り出すにはどのようにすれば良いのでしょうか? 現状は、後処理で、/txt|TXT/でマッチさせています。 opendir(DIR,"./DATA/"); @file=readdir(DIR); closedir(DIR); foreach $myfilename(@file){ if($myfilename=~/txt|TXT/){ print "$myfilename\n"; #確認用 } } よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • FileDateTime

    Dim MyFileName As String Dim MyPath As String Dim NewName As String Dim objFS As FileSystemObject Dim objFol, shellObj, folderObj, MyFolderName, myFile Dim New撮影日時 As String Sub test() MyFileName = "C:\Users\写真" Set objFS = CreateObject("Scripting.FileSystemObject") Set shellObj = CreateObject("Shell.Application") With objFS With .GetFolder(MyFileName) For Each MyFolder In .SubFolders MyPath = MyFileName & "\" & MyFolder.Name & "\" Set objFol = objFS.GetFolder(MyPath) Set folderObj = shellObj.Namespace(MyPath) MyFileName = Dir(MyPath & "*.*") Do While MyFileName <> "" ’ここでエラー New撮影日時 = FileDateTime(MyPath & folderObj.ParseName(MyFileName)) MyFileName = Dir() Loop Next End With End With Set objFS = Nothing End Sub このコードは何が変ですか? 写真フォルダに入っているサブフォルダの写真ファイルの撮影日時を取得したいのですが FileDateTime(MyPath & folderObj.ParseName(MyFileName)) で 実行時エラー_91「オブジェクト変数またはWithブロック変数が設定されていません」 になります。 原因がわかりません。 オフィス2010、アクセスです。

  • アクセスでテキストデータの取込

    アクセスでデータ取込行っているのですが、 テキストデータが2個になったときに テキストデータを二つ取り込みではなく、 テキストデータを2回取り込んでしまってます。 テキストデータの名前は20080222152953.txt VBでの取り込みは strInFName = Dir(TxB04) strInFPath = strInFDir + strInFName If MsgBox("ファイルを取込します。 ", vbOKCancel) = vbCancel Then Exit Sub End If ErrFlg = False myPath = "D:\" myfilename = Dir(TxB04) Do Until myfilename = "" DoCmd.TransferText acImportDelim, , "テーブル名", myPath & strInFName, False myfilename = Dir() Loop という形で行っています。 ご指導宜しくお願い致します。

  • (VBA) Dir 関数で取得するファイル一覧の順序

    タイトルの通り、下記のサンプルコードを実行して取得するファイル一覧の順序についての質問です。 Public Sub Test1() Dim WSH As Object Dim MyPath As String Dim MyFileName As String Set WSH = CreateObject("WScript.Shell") MyPath = WSH.SpecialFolders("MyDocuments") MyFileName = Dir(MyPath & "\" & "*.*") Do Until MyFileName = "" MsgBox MyFileName MyFileName = Dir Loop Set WSH = Nothing End Sub (質問) ファイル名の昇順では取得できないようですが、もしファイル名の昇順に並べ替えるとしたら、 どのように処理したらよいのでしょうか?

  • 特定の名前のシートがあるか確認するには

    1つのフォルダの中に 4つのエクセルファイルがあります。 そのエクセルファイルの中に12というファイル名がある場合は メッセージを出したいと考えて以下のコードを書きました。 この4つのファイルのうち1つのファイルに12のシートを 存在させてみて、以下のコードで実行しました。 Sub シートの確認2() Const MyPath As String = "C:\test\" Dim MyBook As Workbook Dim MyFileName As String Dim MyRng As Range Dim i As Long Dim ws As Worksheet, flag As Boolean MyFileName = Dir(MyPath & "*.xlsx") Do While MyFileName <> "" If ThisWorkbook.Name <> MyFileName Then Set MyBook = Workbooks.Open(MyPath & MyFileName) For i = 1 To Worksheets.Count If Worksheets(i).Name <> "12" Then MsgBox "[12]シートが存在しません。" Else MsgBox "[12]シートが存在します。" End If Next i MyBook.Close End If MyFileName = Dir() Loop End Sub すると、 12という名前のあるシートを持つブックの場合、 "[12]シートが存在しません。" "[12]シートが存在します。" の両方のメッセージが出てきます。 おそらく考えるに そのブックにはシートが2枚あり、 そのうち1つが12という名前のシートであり もう一つは違う名前なので このような現象が出てくるのではないかと。 ただ単純に、その同一フォルダ内のブックに12というがあるかないかを 取得するにはどうしたらよいでしょうか?

  • Rubyで\を\\に置換したい。

    Rubyで"\"マークを"\\"に置換しようとして、以下の様に プログラムを書きましたが、うまくいきません。 "\\aaa"となるようにするには、どうしたらよいでしょうか? %cat aa.txt \aaa %a aa.txt \aaa %cat a #!/usr/bin/ruby while l = gets print l.gsub(/\\/,'\\\\') end