質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

204閲覧

標準添付ライブラリのRDocモジュールは、どこで、どのように、指定されたファイルを読み込んでいるのでしょうか?

tuvalu

総合スコア136

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2017/08/27 06:36

独学でRubyを勉強しているものです。

少し面倒くさいと思われる質問です。
おもしろいと思われた方、おつきあい願えたらと思います。

textファイルを、htmlに変換する簡単なスクリプトを書いていたのですが、書いていると欲が出て来て、

見出しの記述 = マークは<h1></h1>、 == で<h2></h2>、(以降、====== <h6></h6>まであり)、に変換
と、
文字の装飾の記述 +word+ で太字、word で斜体、+word+ でタイプ体に変換

くらいだけも、RDocのマークアップを取り入れられたらと思うようになりました。

Ruby

1original_text_file_name = File.basename($*[0]) #変換したい元のファイル名 2original_file_extension_name = File.extname($*[0]) #変換したい元のファイルの拡張子 3 4puts "実行中のRubyのスクリプトファイル:#{$0}" 5puts "変換するファイル:#{original_text_file_name}" 6puts "検出された拡張子:#{original_file_extension_name}" 7 8if original_file_extension_name == '' #もし拡張子がなければ、 9 html_file_name = original_text_file_name.concat('.html') #ただ単に`.html'を追加 10else 11 html_file_name = original_text_file_name.sub(original_file_extension_name, '.html') #拡張子を`html'に変換 12end 13 14begin 15 puts "これらから #{html_file_name} を生成します。。" 16 17 original_file = $*[0] 18 19 20File.open(original_file) do |text| 21 text.each_line do |line| 22#汎用変換エリア 23 line.gsub!(/&/, '&amp;') 24 line.gsub!(/</, '&lt;') 25 line.gsub!(/>/, '&gt;') 26 line.gsub!(/"/, '&quot;') 27 line.gsub!(/\//, '&frasl;') 28 line.gsub!(/¥/, '&yen;') 29 #line.gsub!(/\\/, '&#92;') 30 line.gsub!(/#/, '&#35;') 31 line.gsub!(/\n/, '<br>') 32 line.gsub!(/\s/, '&nbsp;') 33 line.gsub!(/\t/, '&nbsp;&nbsp;') 34 #line.gsub!(/\bruby\b/i, "<b>#{$&}</b>") 35#RDOC見出し変換エリア 36 if line =~ /^={6}/ then 37 line.sub!(/^={6}/, '<h6>').sub!(/<br>/, '</h6>') 38 elsif line =~ /^={5}/ then 39 line.sub!(/^={5}/, '<h5>').sub!(/<br>/, '</h5>') 40 elsif line =~ /^={4}/ then 41 line.sub!(/^={4}/, '<h4>').sub!(/<br>/, '</h4>') 42 elsif line =~ /^={3}/ then 43 line.sub!(/^={3}/, '<h3>').sub!(/<br>/, '</h3>') 44 elsif line =~ /^={2}/ then 45 line.sub!(/^={2}/, '<h2>').sub!(/<br>/, '</h2>') 46 elsif line =~ /^={1}/ then 47 line.sub!(/^={1}/, '<h1>').sub!(/<br>/, '</h1>') 48 end 49#RDOCリスト変換エリア 50 if line =~ /^\*/ then 51 line.sub!(/\*(&nbsp;)*/, '<li>').sub!(/<br>/, '</li>') 52 elsif line =~ /^-/ then 53 line.sub!(/\-(&nbsp;)*/, '<li>').sub!(/<br>/, '</li>') 54 end 55#RDOC装飾変換エリア 56 line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>") if line =~ /\*((.+?)[^,|(&nbsp;)])\*/ 57 line.sub!(/\_((.+?)[^,|(&nbsp;)])\_/, "<em>#{$1}</em>") if line =~ /\_((.+?)[^,|(&nbsp;)])\_/ 58 line.sub!(/\+((.+?)[^,|(&nbsp;)])\+/, "<tt>#{$1}</tt>") if line =~ /\+((.+?)[^,|(&nbsp;)])\+/ 59 60 File.open(html_file_name, 'a') do |html| 61 html.puts(line) 62 end 63 end 64end 65rescue => e 66 puts "エラーが発生しました。" 67 puts "エラー内容:#{e.message}" 68ensure 69 puts "プログラムを終了します。" 70end 71

でも、こんなんじゃ、うまく動かないことがわかりました。
どうも、元々のファイルの読み方自体がなってないようです。
each_lineで一行ずつ扱うと、一行に、+word+ が2回あったりすると、$1などの組込変数に最初の1つしか格納されないからです。

そこで、ああ、いいお手本があるじゃないかと思い付き、RDocのソースコードを参考にしようと一通り目を通しました。

ところが、なさけないことに、ソースコードを追いかけてみましたが、わからずじまいでした。。
https://github.com/ruby/rdoc/blob/master/lib/rdoc/rdoc.rb
今まで、テキストなどでは、

filename = ARGV[0]
file = File.open(filename)
text = file.read
text.each_line do |line|
やりたい処理
end

みたいなやり方しか見たことがなく、他のファイルの読み込み方を知りません。
そしてRDocのソースコード中にこんな感じの記述を見つけられないのでした。。
レベルが低くて誠にすみませんが、このRDocは一体、どこで、どのように、指定されたファイルを読み込んでいるのでしょうか?
教えていただけたら嬉しいです!
また、記載したコードにについてダメなところを教えて頂けたらと思います。
面倒くさい質問だと思いますがよろしくお願い申し上げます!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Rdocは読んでませんが、

Ruby

1line.gsub!(/\*(.+?)\*/) {"<b>#{$1}</b>"}

のように、ブロック付きのgsubを使えばいいと思います。
また、[^,|(&nbsp;)]の意図が不明ですが、これは、
, | ( & n b s p ; )のどれでも無い1文字」
という意味ですよ。

あと、1行ずつ読む必要は無く、ファイル全体を一気に変数に代入することもできます。
対象ファイルがギガバイト単位でなければ十分。

投稿2017/08/27 12:42

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuvalu

2017/08/29 00:04

ご回答ありがとうございます。おっしゃる通りです。直します。 正規表現に関してはトライアンドエラーみたいな感じで、やればやるどほ訳けがわかんなくなってしまっているのが実情です。。お恥ずかしい限りです。。もっとわかるようになりたいです。 ありがとうございます!
guest

0

ベストアンサー

ソースを検索すると

  • lib/rdoc/encoding.rb
  • lib/rdoc/parser.rb

あたりで普通にファイルを読む処理がありますね。 https://github.com/ruby/rdoc/search?utf8=%E2%9C%93&q=open&type=

each_lineで一行ずつ扱うと、一行に、+word+ が2回あったりすると、$1などの組込変数に最初の1つしか格納されないからです。

gsub使えばいいのではないかとおもうのですが。

追記

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>") if line =~ /\*((.+?)[^,|(&nbsp;)])\*/

多分、最初は

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>#{$1}</b>")

こう書いていて上手く置換が行われないので上記のコードにしたんじゃないかと想像します。sub/gsubの置換後の文字列に正規表現でキャプチャした結果を使いたい時は$1ではなく\1を使います。

https://docs.ruby-lang.org/ja/latest/class/String.html#I_GSUB--21の注意を参照

line.sub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>\\1</b>")

(置換結果がダブルクオーテーションのリテラルになっているので\\になってるのに注意)

sub!をgsub!に変えれば、複数の*なんとか*があっても対応出来ます。

line.gsub!(/\*((.+?)[^,|(&nbsp;)])\*/, "<b>\\1</b>")

ただ、どのみちこれでも正規表現がおかしいので意図した結果にはなりませんが。

--

パーサ作るのは意外と大変なので、文法にこだわりがないのであればmarkdownなどの既存のフォーマット使った方がよいと思います。

https://github.com/vmg/redcarpet

投稿2017/08/27 06:51

編集2017/08/28 14:36
suzukis

総合スコア1449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tuvalu

2017/08/27 07:22

ご回答ありがとうございます。 頂いたご回答、1つづつ理解するのにお時間ください。 理解でき次第連絡いたします! 誠にありがとうございます!
tuvalu

2017/08/28 23:59

追加のご指導までいただきありがとうございます。覚えます。 ご回答をいただいてから、Rdocとにらめっこしてきましたが、 ずいぶん見通せるようになってきました。どうみてもlib/rdoc/encoding.rb のあたりですよね。 突破口がつかめれば、急にわかった気になってきました。ぼくが探せなかっただけで、特別変わったことをしている訳ではなかったんですね。ありがとうございます。 あと、もう一つわかったことは、ご指摘の通り、簡単では無いことをしようとしていたんですね。 プログラミング自体を独学で勉強して一年ちょっとになりますが、なにか簡単に実装できて、なにが簡単でないのかがわかっていない感じです。 本当に勉強になりました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問