正規表現を盛り込んでみる。

うちのサイトはEmacsMuseを使っているが、同ソフトで対応していないルビの処理にrubyonという小さなプログラムを使っている。うちで各種言語をやると必ず試す事でc++でも一度やっているが、当時の書き方と今は全然違うと思うので、再発明がてらやってみる。

書き上げたソース

先日のダンプが元になっている。正規表現には boost::regex を用いた。

////////////////////////////
//
// Rubyon
// Date: 2014/05/28
// Author: hachikun
// License: GPL v2
//
////////////////////////////
//
// #include <ctime>
#include <fstream>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <boost/regex.hpp>
using namespace std;

// 指定テキストファイルを書き出す。
string get_file(string fn)
{
  string r = "";
  string a = "";
  ifstream ifs(fn.c_str());
  if(ifs)
  {
    while(getline(ifs,a)){
      r += (a + "\n");
    }
  /*
    while(!ifs.eof()){
      ifs >> a;
      r += a;
    }
   */
    ifs.close();
  }else{
    r = "ERROR";
  }
  return(r);
}

// 指定ファイルに内容を書き込む。
void set_file(string fn,string str){
  ofstream ofs(fn.c_str());
  ofs << str;
}

// [なんでも&lt;Anything&gt;]
// EmacsMuseにないルビの処理をあらかじめ決めたルールにしたがって独自に行う。
string check_file(string xin)
{
  boost::regex reg("\\[([^&]+)&lt;([^&]+)&gt;\\]");
  string r = regex_replace(xin, reg, "<ruby><rb>$1</rb><rp>(/<rp><rt>$2</rt><rp>)</rp></ruby>"
);
  return(r);
}

int main()
{
    //boost::regex reg("index\\.html");
    boost::regex reg("\\.html\\z");
    //string dir = "../WebWiki/";
    string dir = "./";
    string x,y,z;
    bool bb;
    DIR* dp=opendir(dir.c_str());
    if (dp!=NULL)
    {
      struct dirent* dent;
      do{
        dent = readdir(dp);
        if (dent!=NULL)
        {
          if(regex_search(dent->d_name, reg))
          {
            //x = dir + "index.html";
            x = dir + dent->d_name;
            cout<<x<<" : ";
            y = get_file(x);
            bb = false;
            if (y != "ERROR") // 読み込みエラーでない時
            {
              z = check_file(y);
              if (y != z)
              {
                cout<<"内容に変化があった。:";
                set_file(x,z);
                cout<<"書き込んだ。"<<endl;
              }else{
                cout<<"OK."<<endl;
              }
            }
          }
        }
      }while(dent!=NULL);
      closedir(dp);
    }
}

実行例

以下のようになる。変化がある場合はその旨を表記する。

cd ../WebWiki/;../test4/rubyon
./SalvageTokimemo95.html : OK.
./SecurityFix.html : OK.
./Osage.html : OK.
./SazaeSF.html : OK.
./NvidiaOnLenny.html : OK.
./OLPC.html : OK.
./SchoolMizugi.html : OK.

旧ソース

ちなみに、以前書いた rubyon.cppもあった。恥ずかしいものだけど対比が面白そうなのでこっちも載せてみる。

書き方がCっぽい事もそうだけど、ほんの数年なのに書き方が全然違うのが面白い。当時はポイントの使用に躊躇がなく、そのくせ、類似の処理を二度やったりと不合理なところも見られるのも当時の僕らしいところ。

読み込みの処理方法が結果としてほぼ新旧同一だけど、これは偶然。まぁ短いものですし。

//
// RubyON g++ version
// Date: 2010/10/06
// Author: hachikun
// License: GPL v2
// Version: 0.1a
//
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <boost/regex.hpp>
#include <sys/types.h>
#include <dirent.h>
using namespace std;

bool debug = true;

string aismain(){
    string a = "";
    time_t t = time(0);
    tm *x = localtime(&t);
    if (x->tm_hour > 5 && x->tm_hour < 10) {
        a += "おはようございます";
    } else if (x->tm_hour < 15) {
        a +="こんにちは";
    } else if (x->tm_hour < 18) {
        a +="こ、こんにちは";
    } else {
        a +="こんばんは";
    }
    a += "。";
    return(a);
}

string readFile(string fn){
  char dd[20];
  strcpy(dd,fn.c_str());
  string r = "";
  string x;
  ifstream f(dd);
  while(f && getline(f,x)){
    r = r + x + "\n";
  }
  f.close();
  return(r);
}

void writeFile(string fn,string str){
  char dd[20];
  strcpy(dd,fn.c_str());
  ofstream ofs(dd);
  ofs << str;
}

string replaceStr(string str,string ptn1,string ptn2){
  boost::regex rr(ptn1);
  string r = boost::regex_replace(str, rr, ptn2);
  return(r);
}

bool matchStr(string str,string ptn){
  bool r = false;
  boost::regex rr(ptn);
  boost::smatch m;
  if(boost::regex_search(str, m, rr)) r = true;
  return(r);
}

string rubyFilter(string dx){
  string r = replaceStr(dx,"\\[([^&]+)&lt;([^&]+)&gt;]","<ruby><rb>$1</rb><rp>(</rp><rt>$2</rt
><rp>)</rp></ruby>");
  r = replaceStr(r,"\\[wikipedia:&lt;([^&]+)&gt;]","<a href=http://ja.wikipedia.org/wiki/$1>wi
kipedia:$1</a>");
  return(r);
}

string *dirlist(string d){
  char dd[20];
  strcpy(dd,d.c_str());
  static string s[64];
  int i = 0;
  DIR* dp=opendir(dd);
  if(dp != NULL){
    struct dirent* dent;
    while(dent = readdir(dp)){
      s[i] = dent->d_name;
      i++;
    }
    s[i] = ":__END__:";
  }
  return(s);
}

int main(){
  cout << aismain() << endl;
  cout << "#.. ルビ処理ミニプログラム by hachikunです。" << endl;
  string *p = NULL;
  string x;
  string dx = "";
  p = dirlist(".");
  int i = 0;
  while (*(p+i) != ":__END__:") {
    if(matchStr(*(p+i),".html$")){
      string x = *(p+i);
      //cout << i << ": ";
      //cout << *(p+i) << endl;
      dx = readFile(x);
      if(matchStr(dx,"&gt;]") == true){
        dx = rubyFilter(dx);
        cout << "F:" << x << endl;
        writeFile(x,dx);
      }
    }
    i++;
  }
  cout << "#.. END." << endl;
}