Movable Typeの記事中の文字列を、データベースファイルを直接編集することで一括修正するスクリプト。
・過去の記事 『MovableTypeの「改行を変換する」でコード記述部分まで変換されたのを自動修正する』 のコードを流用する。
■ 検証環境
・Movable Type 3.33 と Movable Type 5.01 の双方で確認
・SQLite データベース
■ 検索置換サンプル
変換前(赤いところを削除)
<a target="_top" … 他の属性等 href="index.html"><img alt="戻る" src="/pics/btn_up.gif" height="25" width="25" />一つ前のメニューに戻る</a>
変換後(青の部分を追加)
<a class="link_return" href="index.html">一つ前のメニューに戻る</a>
■ 検索置換項目を画面表示する(プレビュー)
このスクリプトを、データベースファイル(mtdata.db)のあるフォルダにコピーして、 perl mt_export_btnup.pl > ../test.html
のように実行する。結果はエクスポートして、ブラウザからのほうが見やすい。
mt_export_btnup.pl
#!/usr/bin/perl use warnings; use strict; # 変数の宣言を強制する use DBI; # DBI モジュールを利用する use HTML::Entities; my $dbh = undef; my $sth = undef; my $strQuery = ""; my $strTmp = ""; my $strDsn = 'DBI:SQLite:dbname=./mt-copy.db'; # DSN print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n". "<html>\n". "<head>\n". "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n". "<meta http-equiv=\"Content-Language\" content=\"ja\" />\n". "<style type=\"text/css\">\n". "<!--\n". "table, td, tr { border:solid 1px maroon;font-size:10px;border-collapse: collapse; }\n". "-->\n". "</style>\n". "<title></title>\n". "</head>\n". "<body>\n". "<table>\n"; eval{ # DBに接続 $dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0}); if(!$dbh) { die();} # データを読み込む $strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"/pics/btn_up.gif\"%' or entry_text_more like '%\"/pics/btn_up.gif\"%'"; $sth = $dbh->prepare($strQuery); if($sth){ $sth->execute();} my $counter = 0; while(my $arrData = $sth->fetchrow_arrayref()) { $counter++; my ($id, $text, $text_more) = @$arrData; my @arr_textline = split(/\n/, $text."\n".$text_more); print "<tr><td>".$id."</td><td><pre>"; my $flag_incode = 0; foreach my $text_line (@arr_textline) { chomp $text_line; if($text_line =~ m/<a\s*.*href\s*="[^"]*"><img\s*.*\s*src\s*=\s*"\/pics\/btn_up.gif"\s*height="25"\s*width="25"\s*\/>/){ print "<span style=\"color:green;\">"; print encode_entities($text_line, '&<>\\\"\''); print "</span>"; print "\n"; } } print "</pre></td></tr>\n"; } if($sth){ $sth->finish();} # DBを閉じる $dbh->disconnect(); print "</table>\n". "<p>total count = ".$counter."</p>\n". "</body>\n". "</html>\n"; }; if($@){ # evalによるDBエラートラップ:エラー時の処理 $dbh->disconnect(); print("DBI error : ".$@."\n"); } exit(0);
■ 置換処理
プレビューで置換ヶ所を確認したら、次のファイルを実行する。
・mt_fix_entry_btnup.plをダウンロードする
mt_export_btnup.pl
#!/usr/bin/perl
use warnings;
use strict;
use DBI;
use HTML::Entities;
my $dbh = undef;
my $sth = undef;
my $strQuery = "";
my $strTmp = "";
my $strDsn = 'DBI:SQLite:dbname=./mtdata.db'; # DSN
my @arr_entry = (); # 修正すべきentry_id
eval{
# DBに接続
$dbh = DBI->connect($strDsn, "", "", {PrintError => 1, AutoCommit => 0});
if(!$dbh) { die();}
# データを読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_text like '%\"/pics/btn_up.gif\"%' or entry_text_more like '%\"/pics/btn_up.gif\"%'";
$sth = $dbh->prepare($strQuery);
if($sth){ $sth->execute();}
my $counter = 0;
while(my $arrData = $sth->fetchrow_arrayref()) {
my ($id, $text, $text_more) = @$arrData;
my @arr_textline = split(/\n/, $text."\n".$text_more);
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/<a\s*.*href\s*="[^"]*"><img\s*.*\s*src\s*=\s*"\/pics\/btn_up.gif"\s*height="25"\s*width="25"\s*\/>/){
$flag_incode = 1;
push(@arr_entry, $id);
$counter++;
last;
}
}
}
if($sth){ $sth->finish();}
print "found ".$counter."topics\n";
foreach my $id (@arr_entry) {
print $id." ...";
# 指定されたentry_idが複数ないか、データ件数を確認する
$strQuery = "select count(*) from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id, DBI::SQL_INTEGER);
if($sth){ $sth->execute();}
my @arr = $sth->fetchrow_array();
if($sth){ $sth->finish();}
if($arr[0] != 1){
print "count(entry_id=".$id.") = ".$arr[0]." , is not only one row\n";
last;
}
# 指定されたentry_idの内容を読み込む
$strQuery = "select entry_id,entry_text,entry_text_more from mt_entry where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $id);
if($sth){$sth->execute();}
my $arrData = $sth->fetchrow_arrayref();
if($sth){ $sth->finish();}
my ($id, $text, $text_more) = @$arrData;
# entry_textとentry_text_moreを修正する
$text = fix_text($text);
$text_more = fix_text($text_more);
# 指定されたentry_idの内容を更新する
$strQuery = "update mt_entry set entry_text = ?, entry_text_more = ? where entry_id = ?";
$sth = $dbh->prepare($strQuery);
$sth->bind_param(1, $text, DBI::SQL_VARCHAR);
$sth->bind_param(2, $text_more, DBI::SQL_VARCHAR);
$sth->bind_param(3, $id, DBI::SQL_INTEGER);
if($sth){$sth->execute();}
if($sth){ $sth->finish();}
print "\n";
}
$dbh->commit();
# DBを閉じる
$dbh->disconnect();
};
if($@){
# evalによるDBエラートラップ:エラー時の処理
$dbh->disconnect();
print("DBI error : ".$@."\n");
}
exit(0);
#
# <img alt="戻る" src="/pics/btn_up.gif" height="25" width="25" /> を削除する
# それを囲む <a href="..."> を <a class="link_return" href="..."> に書き換える
#
sub fix_text {
my $text = shift;
my @arr_textline = split(/\n/, $text);
$text = "";
my $flag_incode = 0;
foreach my $text_line (@arr_textline) {
chomp $text_line;
if($text_line =~ m/<a\s*.*href\s*="[^"]*"><img\s*.*\s*src\s*=\s*"\/pics\/btn_up.gif"\s*height="25"\s*width="25"\s*\/>/){
$text_line =~ s/<a\s*.*href\s*="([^"]*)"><img\s*alt="戻る"\s*src\s*=\s*"\/pics\/btn_up.gif"\s*height="25"\s*width="25"\s*\/>/<a class="link_return" href="$1">/;
}
$text .= ($text_line . "\n");
}
return $text;
}