オープンソースの画像生成AIをセットアップから使い方まで解説する『Stable Diffusion AI画像生成ガイドブック』(ソシム刊)発売中(→本のサポートページ

はてなダイアリーからはてなブログへ引っ越す前にはてな記法をはてなブログ向けに修正する

いきなり追記

本稿は、はてなブログのエントリをまとめて編集する方法がないことを前提に書きました。本稿の投稿後、blogsyncというツールがあることを知りました。

1月28日にダイアリーを編集できなくなったあとはblogsyncを使うと、ダイアリーからインポートしたはてなブログの内容をテキストファイルの編集によって一括で変更できます。

(ただし、エントリごとにテキストファイルが作られる仕様のため、自分のはてなブログ全体を一括で検索・置換するにはgrepなどを使う必要があります)

さらに追記

本稿の末尾で紹介している「はてなブログライター」も、投稿済みのエントリをダウンロードしてテキストファイルとして管理できるようになりました。

拙作「はてなブログライタースプリッタ」を使うと、はてなブログへの投稿をすべて1つにまとめたテキストファイルで管理できるようになるため全文の検索・置換が容易になります。

もひとつ追記

はてなダイアリーはてなブログへインポートしたあとに、はてなブログライターとはてなブログライタースプリッタを使って、エントリの内容をまとめて置換する方法を解説しました。

ここから初出時の本文

はてなダイアリーは1月28日以降は編集できなくなる(はてなブログへの統合スケジュールのお知らせ - はてなダイアリー日記)。はてなダイアリーの書き方(はてな記法)とはてなブログの「はてな記法モード」は微妙に異なり、そのままインポートするとダイアリーのときとは一部異なる表示結果になる。はてなダイアリーはてなブログへインポートする前に、ダイアリーの内容をはてなブログ向けに書き直しておこう。

はてなダイアリーに登録したエントリを全文一括で検索・置換できるようにすれば、ダイアリーの内容をチクチク修正する必要はなくなる。

この記事では、まとめる際に気付いた不具合についても書いている。これは本稿執筆時点のものであり、今後修正される可能性がある。

記事が思った以上に長くなったので、珍しく目次をどうぞ。

はてなダイアリーの内容を全文検索/置換できるようにする

まず、はてなダイアリーの内容を全文検索/置換できるよう、1つのテキストファイルにまとめる。方法は以下で解説している。

これで、ダイアリーの全エントリを1つのテキストファイルにまとめることができる。あとはテキストエディタを使い、はてなブログ向けの書き方に修正すればよい。検索して一括で置換できる修正ならすべての日をまとめて修正できて簡単だ。正規表現での検索・置換を使えば、すべての数字を検索したり、検索結果の一部を取り出して置換する文字列として使うことができたりする。

正規表現が使えるテキストエディタ秀丸エディタ(有料、https://hide.maruo.co.jp/software/hidemaru.html)やサクラエディタ(フリー、https://sakura-editor.github.io/)、macOSならmi(フリー、https://www.mimikaki.net/)などがある。(カッコでくるんだタグを置換時に呼び出す文字は、テキストエディタによっては「\1」「\2」…ではなく「$1」「$2」…のこともあります)

なお、改行を検索するのに「\n」が出てくるが、サクラエディタWindowsの改行(CR+LF)を検索するには「\r\n」と書く。サクラエディタでLFやCRのみの改行も含めて検索するには「\[\r\n]+」と書く(→利用可能な正規表現 - サクラエディタ)。miで改行を表すのは「\r」である(→正規表現 - mi Help)。

また、テキストエディタによっては、正規表現での「<」や「>」は「\<」「\>」と書く必要がある(WZ Editorなど)。使っているテキストエディタのヘルプを参照のこと。

はてなブログ向けにテキストファイルを編集してダイアリーを更新するときは、「ちょっとした更新」になる「-t」オプションをつけるのを忘れずに。ダイアリーの設定によっては自動でトラックバックidコール)を飛ばしまくることになってしまう。管理画面の「設定」-「コメント・トラックバック設定」(「ダイアリーのURL/configcomment」)の下の方にある「自動トラックバック」を「自動トラックバックを送信しない」にしておく。はてなダイアリーに新しいエントリを登録するときは、もちろん「ちょっとした更新」にする必要はない。

追記:はてなブログの内容を全文検索/置換できるようにする

はてなブログの内容を一括で置換できるようにする方法は下の記事で解説しています。


拡張id記法をダイアリー記法に置換

はてなダイアリーで「id:Imamura:20030217:p1」のように、日付を含むid記法を書いている方限定です。id記法については→はてなユーザーにリンクする(id記法) - はてなダイアリーのヘルプ

はてなダイアリーだけで使えるid記法(「id:Imamura:20030217:p1」のような書き方、本稿では「拡張id記法」と呼称)は、はてなブログへ行くと「id:Imamura:20030217:p1」のようなリンクになる。はてなブログでははてなダイアリーと異なり、id記法では「id:~」という書き方しかサポートしていないため。

「id:」の前に「d:」をつけた「[d:id:Imamura:20030217:p1]」という書き方は「ダイアリー記法」といい、これならはてなブログでも使える。じゃあ「id:~」をまとめて「d:id:~」に置換してしまえばいいのかというとそんなことはない。フォトライフ記法(「f:id:~」)が「f:d:id:~」になったり、はてなグループ記法(「g:~:id:~」)が「g:~:d:id:~」になってしまったりする。それに日付などを含まない通常のid記法(「id:~」)ははてなブログでも有効なのでそのままにしておきたい。

加えて、定義リストの記法(「:」で始めて「:~:~」と書く)で2つめの「:」の直後にid記法がある可能性と、行頭がid記法である可能性も考慮して、下のように段階を追って正規表現で検索・置換していく。

  1. 定義リストの2つめの「:」に続けて拡張id記法がある場合にダイアリー記法へ置換
    • ①英字(厳密にはabcdfghiklmnqrsだけと思うが抜けがありそうなのでa~z全部で検索)を除く文字列+②「:」(定義リストの2つめの「:」)+③「id:」+④英数字、「_」、「-」、「+」を含む文字列+⑤「:」+⑥「yyyymmdd(数字8桁)」という文字列を検索して、「[①②d:③④⑤⑥]」に置換する
      • 検索:([^a-zA-Z]:)(id:[a-zA-Z0-9_\-\+]+:\d{8})
      • 置換:[\1d:\2]
  2. idを含む各種のはてな記法を除いて、拡張id記法をダイアリー記法へ置換
    • ①「:」以外の文字列+②「id:」+③英数字、「_」、「-」、「+」を含む文字列+④「:」+⑤「yyyymmdd(数字8桁)」という文字列を検索して、「[①d:②③④⑤]」に置換する
      • 検索:([^:])(id:[a-zA-Z0-9_\-\+]+:\d{8})
      • 置換:[\1d:\2]
  3. 行頭の拡張id記法をダイアリー記法へ置換
    • ①行頭の「id:」+②英数字、「_」、「-」、「+」を含む文字列+③「:」+④「yyyymmdd(数字8桁)」という文字列を検索して、「[①d:②③④]」に置換する
      • 検索:^(id:[a-zA-Z0-9_\-\+]+:\d{8})
      • 置換:[d:\1]

拡張id記法に「d:」をつけてダイアリー記法にしたくないときは、拡張id記法をリンクタグにする。たとえば「id:Imamura:20030217:p1」を「<a href="http://d.hatena.ne.jp/Imamura/20030217/p1">id:Imamura:20030217:p1</a>」のように一括置換すればよい。id:Imamura:20030217#p1(最後の「:」が「#」)という書き方の場合は「<a href="http://d.hatena.ne.jp/Imamura/20030217#p1">id:Imamura:20030217#p1</a>」にする。(方法は省略)

また拡張id記法やダイアリー記法には「d:id:zaikabou:201812」という月単位の書き方もあって、その月のエントリをまとめて表示する「http://d.hatena.ne.jp/zaikabou/201812」へのリンクとなる(id:zaikabouさん、例に出してスイマセン。ダイアリーをはてなブログにインポート済み、かつリダイレクト設定済みの人ということで使わせていただきます)。

はてなダイアリーの内容をはてなブログにインポートすると、はてなダイアリーのURLははてなブログへリダイレクトされる。上のURL(http://d.hatena.ne.jp/zaikabou/201812)はhttp://zaikabou.hatenablog.com/entries/2018/12/00へリダイレクトされ、当該月の1日のエントリが本文も含めてまとめて表示されるのだが、そのエントリの実際のURL(上の場合http://zaikabou.hatenablog.com/entry/20181201/1543590000)と異なるため混乱する。(フィードバック済み)

このような問題を避けるため、月単位のダイアリー記法ははてなブログ向けに書き換えておく。これには移行先のはてなブログのURLが必要になるので、はてなダイアリーをインポートする先のはてなブログをあらかじめ作成しておく。また月単位の表記をしているほかの人のダイアリーがはてなブログに移行していなかったら、あとで移行を確認してから書き換えることになる。

はてなブログでは、1か月分の記事の一覧は「http://zaikabou.hatenablog.com/archive/2018/12」といったURLで閲覧できる。「d:id:zaikabou:201812http://d.hatena.ne.jp/zaikabou/201812)」は「http://zaikabou.hatenablog.com/archive/2018/12」へリンクするよう書き換える。

  1. 拡張id記法での月単位の指定をはてなブログでの月単位の指定に置換
    • ①「:」以外の文字列+②「id:」+③英数字、「_」、「-」、「+」を含む文字列+④「:」+⑤「yyyy(数字4桁)」+⑥「mm(数字2桁)」+⑦数字以外の文字、という文字列を検索して、「①[はてなブログのURL/archive/⑤/⑥:title=②③④⑤⑥]⑦」に置換する
      • 検索:([^:])(id:[a-zA-Z0-9_\-\+]+:)(\d{4})(\d\d)([^\d])
      • 置換:\1[はてなブログのURL/archive/\3/\4:title=\2\3\4]\5
  2. 拡張id記法での月単位の指定をはてなブログでの月単位の指定に置換(行頭にある場合)
    • ①行頭の「id:」+②英数字、「_」、「-」、「+」を含む文字列+③「:」+④「yyyy(数字4桁)」+⑤「mm(数字2桁)」+⑥数字以外の文字、という文字列を検索して、「[はてなブログのURL/archive/④/⑤:title=①②③④⑤]⑥」に置換する
      • 検索:^(id:[a-zA-Z0-9_\-\+]+:)(\d{4})(\d\d)([^\d])
      • 置換:[はてなブログのURL/archive/\2/\3:title=\1\2\3]\4
  3. ダイアリー記法での月単位の指定をはてなブログでの月単位の指定に置換
    • ①「d:id:」+②英数字、「_」、「-」、「+」を含む文字列+③「:」+④「yyyy(数字4桁)」+⑤「mm(数字2桁)」+⑥数字以外の文字、という文字列を検索して、「[はてなブログのURL/archive/④/⑤:title=①②③④⑤]⑥」に置換する
      • 検索:(d:id:[a-zA-Z0-9_\-\+]+:)(\d{4})(\d\d)([^\d])
      • 置換:[はてなブログのURL/archive/\2/\3:title=\1\2\3]\4

タイトル内にあるリンクを外に出す

※ダイアリーのエントリのタイトルにリンク(「<a href="~">」)やid記法(「id:~」)、ASIN/ISBN記法(「ASIN:~」や「ISBN:~」)、URLを書いている方限定です

はてなダイアリーはサービスイン当初、タイトルの前の「■」がそのエントリへのリンクになっていて、タイトルそのものは素のテキストだった。今も「設定」-「記事の設定」-「表示モードの選択」-「見出し」(ダイアリーのURL/configview)で「見出しを1段で表示」にするとその表示を選択できる。なのでタイトル内に別のURLへのリンクを書くことができた。

一方、はてなブログではタイトル全体がそのエントリへのリンクになる。そのため、ダイアリーで「*p1*<a href="http://www.hatena.ne.jp/">はてな</a>について」のような書き方をしていたのをはてなブログへインポートすると、リンク先にジャンプできない記事になる。そこで、タイトル内のリンクをタイトルの次の行へ移動する。リンクはリスト記法(行頭が「-」)で書くことにする。

  1. タイトル内のa要素を次の行へ移動する
    • ①行頭が「*」+②「*」以外で始まる任意の文字列(行頭に「**」と書く小見出し記法を検索しないようにする)+③「<a」+④「>」以外の任意の文字列+⑤「href=」+⑥「"」「'」(あれば)+⑦「"」か「'」以外の任意の文字列+⑧「"」か「'」(あれば)+⑨「>」以外の任意の文字列(あれば)+⑩「>」+⑪「<」以外の任意の文字列+⑫「</a>」+⑬行末までの任意の文字列、という文字列を検索して、「①②⑪⑬\n-③④⑤⑥⑦⑧⑨⑩⑪⑫」に置換する
      • 検索:^(\*[^\*].*)(<a href=["']?[^"']+["']?>)([^<]+)(</a>)(.*)$
      • 置換:\1\3\5\n-\2\3\4
  2. タイトル内のid記法を次の行へコピーする
    • ①行頭が「*」+②「*」以外で始まる任意の文字列(行頭に「**」と書く小見出し記法を検索しないようにする)+③英字と「:」以外の文字列+④英字と「:」の文字列(あれば)+⑤「id:」+⑥英数字と「_」「:」「#」「-」「+」を含む文字列+⑦行末までの任意の文字列(あれば)、という文字列を検索して「①②③④⑤⑥⑦\n-④⑤⑥」に置換する
      • 検索:^(\*[^\*].*[^a-zA-Z:]+)([a-zA-Z:]*:?id:[a-zA-Z0-9_:#\-\+]+)(.*)$
      • 置換:\1\2\3\n-\2
  3. タイトル内のASIN/ISBN記法を次の行へコピーする
    • ①行頭が「*」+②「*」以外で始まる任意の文字列(行頭に「**」と書く小見出し記法を検索しないようにする)+③「ASIN:」か「ISBN:」+④英数字の文字列(10文字か13文字だが煩雑になるため単なるくり返しで判断)+⑤行末までの任意の文字列(あれば)、という文字列を検索して「①②③④⑤\n-③④」に置換する
      • 検索:^(\*[^\*].*)([AaIi][Ss][IiBb][Nn]:[a-zA-Z0-9]+)(.*)$
      • 置換:\1\2\3\n-\2
  4. URLを含むタイトルを次の行へコピーする
    • ①行頭が「*」+②「*」以外で始まる任意の文字列(行頭に「**」と書く小見出し記法を検索しないようにする)+③「http://」や「https://」で始まり、英数字と「.」「,」「;」「/」「~」「-」「(」「)」「_」「#」「?」「%」「&」「=」「!」「+」を含む文字列(←ここはもうちょっと工夫が必要かも)、という文字列を検索して「①②③\n-③」に置換する
      • 検索:^(\*[^\*].*)(https?://[a-zA-Z0-9\.,;/~\-\(\)_#\?%&=\!\+]+)(.*)$
      • 置換:\1\2\3\n-\2

一行内に複数のa要素やid記法などがあるかもしれない場合、検索結果がなくなるまで何回か検索・置換をくり返す。

最後に、タイトル内に「https?://」や「id:」、「ASIN:」、「ISBN:」があって次の行が「-」以外で始まる行がないか、検索しておくとよさそう。検索文字列は「^\*[^\*].*(https?://|id:|[AaIi][Ss][IiBb][Nn]:).*\n[^\-]」。

定義リストの記法内の「:」を「&#58;」に置換

※ダイアリーで定義リスト記法(「:~:~」)を使っている方限定です。定義リスト記法については→定義リストをつくる(定義リスト記法) - はてなダイアリーのヘルプ

はてなダイアリーには定義リストの記法がある。行頭に「:」、次に「:」が出るまでがdt要素(定義リストの見出し)、そこから行末までがdd要素(定義リストの本文)になる。

このdt要素部分に「:」を書こうとすると、それが定義リストの区切り文字として認識されてしまう。それを回避するのに「:」を「[]:[]」とエスケープする手法があった。これはお手軽でよかったのだが、はてなブログでは解釈が変わった。エスケープしてあっても、行頭の「:」の次に「:」が出るとそこでdt要素が終わる。はてなブログでdt要素に「:」を書きたいときは「:」の代わりに「&#58;」と書くようにする。

  1. 「[]:[]」を「&#58;」に変換する(これは正規表現を使わず通常の検索・置換で)
    • 検索::
    • 置換:&#58;
      • 自分の場合「まんぷく[]::[]日記」という書き方が多かったので上に加えて「::」を「&#58;&#58;」に検索・置換した
  2. 行頭の「:」と次の「:」の間に「[]」がある行を検索する。「[]~[]」の間に「:」があるかは判定しないので一括置換はせず、区切り文字ではない「:」を「&#58;」にし、「[]」を削除するなどを手作業で行う
    • ①行頭に「:」+②「:」を除く任意の文字列(あれば)+③「[]」を検索
      • 検索:^:[^:]*\[\]

行頭の「:」と次の「:」の間にURLがあればhttp記法に置換する

※ダイアリーで定義リスト記法(「:~:~」)を使っている方限定です。定義リスト記法については→定義リストをつくる(定義リスト記法) - はてなダイアリーのヘルプ

定義リストの記法でdt要素内にURLがある場合、「:<a href="http://~">~</a>:~」と書いていると「http:」の「:」を区切り文字と誤解してdt要素が終わってしまう(URLやHTMLタグ内の「:」は定義リスト記法の区切り文字にしないでほしい→フィードバック済み)。「[http://~:title=~]」というhttp記法に置換する。

  1. 定義リスト記法で2つめの区切り文字までにリンクのタグがあったらhttp記法に書き換える
    • ①行頭に「:」+②「:」や「<」を除く任意の文字列(あれば)+③「<a href=」+④「"」か「'」(あれば)+⑤「"」「'」以外の任意の文字列(ここがURL)+⑥「"」か「'」(あれば)+⑦「 」(半角スペース)(あれば)+⑧「>」以外の任意の文字列(あれば)+⑨「>」+⑩「<」以外の任意の文字列(ここがリンク文字列)+⑪「</a>」、という文字列を検索して、「①②[⑤:title=⑩]」に置換する
      • 検索:^(:[^:<]*)<a.*href=["']?([^"'>]+)["']? ?[^>]*>([^<]+)<a>
      • 置換:\1[\2:title=\3]\4

この検索/置換にはいくつか注意がある。

  • dt要素内にリンクタグが複数ある可能性を考えて、検索されなくなるまで検索/置換する
  • 「<a rel="nofollow" href~」のように「<a 」に「href~」が続かない書き方をしていると検索されない(正規表現で「*」に続く「?」による最短一致検索ができるなら、「a href=」の部分を「a.*?href=」と書くこともできるが、これを「[http://~:title=~]」に書き換えると「rel="nofollow"」という属性がなくなってしまうので一長一短)
  • 「<a href="~">」と「</a>」の間が文字ではなく画像(「<img src="~">」)のときは「[http://~:title=<img src="~">]」となってしまうので、そういうのは改めて「[http://~:image=画像のURL]」と置換する(方法は省略)
    • 画像に特定のクラス(「class="~"」)を割り当てる必要があるとお手上げなので、定義リストのはてな記法は使わず「><dl><dt>~</dt><dd>~<dd></dl><」とHTMLのタグにするほかなさそう(方法は省略)
  • 最後に、検索しきれなかったものを探して個別に対処する
    • ①行頭に「:」+②「:」を除く任意の文字列(あれば)+③「[」以外の文字+④「http://」や「https://」で始まり、英数字と「.」「,」「;」「/」「~」「-」「(」「)」「_」「#」「?」「%」「&」「=」「!」「+」を含む文字列(←さっきと同じ)を検索する(書き方はさまざまなので一括置換せず、一つずつ書き換える)
      • 検索:^:[^:]*[^\https?://[a-zA-Z0-9\.,;/~\-\(\)_#\?%&=\!\+]+

追記(2019年7月16日)

「:[URL]:説明」という書き方でも、はてなブログ側でうまく解釈してくれないケースがあるとわかりました。具体例は以下です。

問題あり
:はてな<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです
:<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです(追記:2020年1月10日までに修正された)
:http://www.hatena.ne.jp/:はてなです
:はてな[http://www.hatena.ne.jp/:title=はてな]:はてなです
:はてな[http://www.hatena.ne.jp/:bookmark]:はてなです
:はてな[http://www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
:はてな[http://www.hatena.ne.jp/]:はてなです
:はてな [http://www.hatena.ne.jp/]:はてなです

問題なし
:[http://www.hatena.ne.jp/:title=はてな]:はてなです
:[http://www.hatena.ne.jp/:title=はてな]はてな:はてなです
:[http://www.hatena.ne.jp/:title=はてな] はてな:はてなです
:[http://www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
:[http://www.hatena.ne.jp/:title=はてな:bookmark]はてな:はてなです
:[http://www.hatena.ne.jp/]:はてなです
:[http://www.hatena.ne.jp/:bookmark]:はてなです
:<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです

結果は以下のようになります。

問題あり

はてな
//www.hatena.ne.jp/">はてな:はてなです
はてな
はてなです(追記:2020年1月10日までに修正された)
http
//www.hatena.ne.jp/:はてなです
はてな[http
//www.hatena.ne.jp/:title=はてな]:はてなです
はてな[http
//www.hatena.ne.jp/:bookmark]:はてなです
はてな[http
//www.hatena.ne.jp/:title=はてな:bookmark]:はてなです
はてな[http
//www.hatena.ne.jp/]:はてなです
はてな [http
//www.hatena.ne.jp/]:はてなです

問題なし

はてな
はてなです
はてなはてな
はてなです
はてな はてな
はてなです
はてな
はてなです
はてなはてな
はてなです
http://www.hatena.ne.jp/
はてなです
はてなです
はてな
はてなです

この追記を書いた2019年7月16日現在、以下のようなHTMLが生成されています。(キーワードへのリンクは除去しました)

        <p>問題あり</p>
<dl>
<dt>はてな</dt>
<dd>//www.hatena.ne.jp/">はてな</a>:はてなです</dd>
<dt></dt>
<dd>//www.hatena.ne.jp/">はてな</a>:はてなです</dd>
<dt>http</dt>
<dd>//www.hatena.ne.jp/:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:title=はてな]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:bookmark]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/:title=はてな:bookmark]:はてなです</dd>
<dt>はてな[http</dt>
<dd>//www.hatena.ne.jp/]:はてなです</dd>
<dt>はてな [http</dt>
<dd>//www.hatena.ne.jp/]:はてなです</dd>
</dl><p>問題なし</p>

<dl>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a></dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a>はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a> はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a></dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">&#x306F;&#x3066;&#x306A;</a><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a>はてな</dt>
<dd>はてなです</dd>
<dt><a href="http://www.hatena.ne.jp/">http://www.hatena.ne.jp/</a></dt>
<dd>はてなです</dd>
<dt><a href="https://b.hatena.ne.jp/entry/http://www.hatena.ne.jp/" class="http-bookmark"><img src="https://b.hatena.ne.jp/entry/image/http://www.hatena.ne.jp/" alt="" class="http-bookmark" /></a></dt>
<dd>はてなです</dd>
</dl>

現状、行頭の「:」と次の「:」の間に地の文に続けてhttp記法があるともうお手上げで、定義リスト記法ではなく「><dl><dt>~</dt><dd>~<dd></dl><」というdl要素のHTMLを書くしかない。

追記(2020年1月10日)

「不具合を修正しました」というメールが来たのでうきうきしながらチェックしたら、直っていたのは「:<a href="http://www.hatena.ne.jp/">はてな</a>:はてなです」という書き方だけだった。ガックシ。上のリストを送って再度修正をお願いした。

blockquoteタグ内の「cite」要素は展開されない

※ダイアリー内で引用記法を使わず「<blockquote cite="URL" title="引用元のタイトル">」のように書いている方限定です。引用記法については→引用ブロックを作る(引用記法) - はてなダイアリーのヘルプ

><blockquote cite="URL" title="引用元のタイトル"><
引用の内容
></blockquote><

はてなダイアリーで上のように書くと、下のように展開される。上の「cite="~"」や「title="~"」の内容が、「引用の内容」のあとに<cite>~</cite>タグに展開されているのが特徴である。

<blockquote title="引用元のタイトル" cite="URL">
	<p>引用の内容</p>
	<cite><a href="URL" target="_blank">引用元のタイトル</a></cite></blockquote>

表示結果は下の通り。(URLは一例)

引用の内容

引用元のタイトル

しかしはてなブログでは、<blockquote>タグの中にcite属性やtitle属性を書いておいても<cite<タグを生成してくれない。はてなブログでは引用文だけ読むことになり、引用元のURLやタイトルは表示されない。これはいかん。

引用記法ならそういうことはない。引用記法は下のようなもの。

>URL:title=引用元のタイトル>
引用の内容
<<

これははてなブログでもちゃんと<cite>タグを生成してくれる。表示結果は下の通り。(URLは一例)

引用の内容

引用元のタイトル

じゃあ「<blockquote cite="URL" title="~">」を「>URL:title=~>」に置換して、次に「</blockquote>」を「<<」に置換して…とやろうとして考え始めたら、ことはそう簡単ではないと気がついた。

blockquote要素の書き方はさまざまなパターンが考えられる。実際、自分の過去日記を検索してみると引用記法が実装される前に「<blockquote cite="URL" title="~">」を手書きしているところがたくさんあった。いくつかはcite属性とtitle属性の順序が逆で「<blockquote title="~" cite="URL">」なんて書いていたりする。それぞれきちんと「>URL:title=~>」に置換しておかないと「<blockquote~>」タグと「</blockquote>」タグの対応が崩れてしまう。

以下は、blockquote要素の書き方をある程度自動的に「>~>」や「<<」に置換する検索パターンである。「</blockquote>」タグもなるべくうまく「<<」に置換するが、ひと通り置換したら「<blockquote」と「</blockquote」を検索して(正規表現で「</?blockquote」を検索)、対応する終了タグや開始タグが「<<」や「>>」になっていたらうまく書き換えてほしい。

  1. 「><blockquote cite="URL" title="引用元のタイトル"><」という行を「>URL:title=引用元のタイトル>」に置換
    • ①行頭が「>」(あれば)+②「<blockquote cite="」+③「http://」や「https://」で始まり「"」を含まない文字列(URL)+④「" title="」+⑤「"」を含まない文字列(引用元のタイトル)+⑥「">」+⑦「<」(あれば)で行末、という文字列を検索し、「①③:title=⑤>」に置換する
      • 検索:^>?<blockquote cite="([^"]+)" title="([^"]+)"><?$
      • 置換:>\1:title=\2>
  2. 上の「cite="~"」と「title="~"」を入れ替えて検索・置換
    • ①行頭が「>」(あれば)+②「<blockquote title="」+③「"」を含まない文字列(引用元のタイトル)+④「" cite="」+⑤「http://」や「https://」で始まり「"」を含まない文字列(URL)+⑥「">」+⑦「<」(あれば)で行末、という行を検索し、「①③:title=⑤>」に置換する
      • 検索:^>?<blockquote title="([^"]+)" cite="([^"]+)"><?$
      • 置換:>\2:title=\1>
  3. 上の「cite="~"」と「title="~"」がないパターン(「><blockquote><」という行)を「>>」に置換
    • ①行頭が「>」(あれば)+②「<blockquote">」+③「<」(あれば)で行末、という行を検索し、「>>」に置換する
      • 検索:^>?<blockquote><?$
      • 置換:>>
  4. 「><blockquote cite="URL"><」という行を「>URL:title>」に置換(※「URL」に「:title」をつけるとそのページのタイトルが表示される。これまで同様URLを表示したいときは「>URL>」に置換する)
    • ①行頭が「>」(あれば)+②「<blockquote cite="」+③「http://」や「https://」で始まり「"」を含まない文字列(URL)+④「">」+⑤「<」(あれば)で行末、という行を検索し、「①③:title>」に置換する
      • 検索:^>?<blockquote cite="([^"]+)"><?$
      • 置換:>\1:title>(※これまで同様URLを表示したいときは「>\1>」に置換)
  5. 「>」が行頭にあり、「<blockquote cite="URL" title="引用元のタイトル"><」と続く文字列(ここで行末にならない)を「>URL:title=引用元のタイトル>[改行]><」に置換(「><blockquote~><p>~」や「><blockquote~>[改行]<p>~」といった書き方を想定)
    • ①行頭が「>」+②「<blockquote cite="」+③「http://」や「https://」で始まり「"」を含まない文字列(URL)+④「" title="」+⑤「"」を含まない文字列(引用元のタイトル)+⑥「">」+⑦改行(あれば)+⑧「<」+⑨任意の文字、という文字列を検索し、「①③:title=⑤>[改行]>⑧⑨」に置換する
      • 検索:^><blockquote cite="([^"]+)" title="([^"]+)">\n?(<.)
      • 置換:>\1:title=\2>\n>\3
  6. 上の「cite="~"」と「title="~"」を入れ替えて検索・置換
    • ①行頭が「>」+②「<blockquote title="」+③「"」を含まない文字列(引用元のタイトル)+④「" cite="」+⑤「http://」や「https://」で始まり「"」を含まない文字列(URL)+⑥「">」+⑦改行(あれば)+⑧「<」+⑨任意の文字、という文字列を検索し、「①⑤:title=③>[改行]>⑧⑨」に置換する
      • 検索:^><blockquote title="([^"]+)" cite="([^"]+)">\n?(<.)
      • 置換:>\2:title=\1>\n>\3
  7. 上の「cite="~"」と「title="~"」がないパターンを検索・置換
    • ①行頭が「>」+②「<blockquote">」+③改行(あれば)+④「<」+⑤任意の文字、という文字列を検索し、「①>[改行]>④⑤」に置換する
      • 検索:^><blockquote>\n?(<.)
      • 置換:>>\n><\1
  8. 「>」が行頭にあり、「<blockquote cite="URL" title="引用元のタイトル">」と続き(ここで行末にならない)、さらに「<」でない文字が続く文字列を検索して「>URL:title=引用元のタイトル>[改行]任意の文字」に置換(「<blockquote~>」タグは続けて文字を書けるが、「>URL:title=引用元のタイトル>」は独立した行である必要があるため。また「任意の文字」はもともとは<p>~</p>タグでくるまれない書き方だが、引用記法の「>>」に続けて<p>タグの自動生成を抑止する書き方はないため置換後はp要素になる)
    • ①行頭が「>」+②「<blockquote cite="」+③「http://」や「https://」で始まり「"」を含まない文字列(URL)+④「" title="」+⑤「"」を含まない文字列(引用元のタイトル)+⑥「">」+⑦「<」以外の任意の文字、という文字列を検索し、「>③:title=⑤>[改行]⑦」に置換する
      • 検索:^><blockquote cite="([^"]+)" title="([^"]+)">([\^<])
      • 置換:>\1:title=\2>\n\3
  9. 上の「cite="~"」と「title="~"」を入れ替えて検索・置換
    • ①行頭が「>」+②「<blockquote title="」+③「"」を含まない文字列(引用元のタイトル)+④「" cite="」+⑤「http://」や「https://」で始まり「"」を含まない文字列(URL)+⑥「">」+⑦「<」以外の任意の文字、という文字列を検索し、「>⑤:title=③>[改行]⑦」に置換する
      • 検索:^><blockquote title="([^"]+)" cite="([^"]+)">([^<])
      • 置換:>\2:title=\1>\n\3
  10. 上の「cite="~"」と「title="~"」がないパターンを検索・置換(※任意の文字の冒頭には<p>が追加される。cite要素やtitle要素がないなら><blockquote>~のままでもいいかもしれないが、</blockquote><を置換する際、対応する開始タグにこれらの要素があるかどうかを判別できないためこれも「>>」に置換しておく)
    • ①行頭が「>」+②「<blockquote>」+③「<」以外の任意の文字、という文字列を検索し、「>>[改行]③」に置換する
      • 検索:^><blockquote>([\^<])
      • 置換:>>\n\3
  11. 任意の文字に続けて「>」があり、続けて「<blockquote cite="URL" title="引用元のタイトル"><」(ここで行末)という文字列を検索して「任意の文字><[改行]>URL:title=引用元のタイトル>」に置換(「~</p><blockquote~><」のような書き方を想定)
    • ①任意の文字+②「>」+③改行(あれば)+④「<blockquote cite="」+⑤「http://」や「https://」で始まり「"」を含まない文字列(URL)+⑥「" title="」+⑦「"」を含まない文字列(引用元のタイトル)+⑧「"><」(ここで行末)という文字列を検索し「①><[改行]>⑤:title=⑦>」に置換する
      • 検索:(.)>\n?<blockquote cite="([^"]+)" title="([^"]+)"><$
      • 置換:\1><\n>\2:title=\3>
  12. 上の「cite="~"」と「title="~"」を入れ替えて検索・置換
    • ①任意の文字+②「>」+③改行(あれば)+④「<blockquote title="」+⑤「"」を含まない文字列(引用元のタイトル)+⑥「" cite="」+⑦「http://」や「https://」で始まり「"」を含まない文字列(URL)+⑧「"><」(ここで行末)という文字列を検索し「①><[改行]>⑦:title=⑤>」に置換する
      • 検索:(.)>\n?<blockquote title="([^"]+)" cite="([^"]+)"><$
      • 置換:\1><\n>\3:title=\2>
  13. 上の「cite="~"」と「title="~"」がないパターンを検索・置換
    • ①任意の文字+②「>」+③改行(あれば)+④「<blockquote><」(ここで行末)という文字列を検索し「①><[改行]>>」に置換する
      • 検索:(.)>\n?<blockquote><$
      • 置換:\1><\n>>

上でcite属性やtitle属性は「"」~「"」で囲む前提で書いているが、ここは「'」~「'」で囲んだり、そもそもこのような引用符をつけずに書いたりもできる。わーもう大変。「"」のところを「["' ]」で書いてもだいたい大丈夫だと思うけれど、そもそも引用符に「'」を使うのは「'~'」の範囲に「"」を書きたいからだったりする。そうなると「'~"~'」という範囲の「'~"」までしか検索にかからないので気を抜けない。もし「["' ]」と書くなら一括置換は絶対にやめて、確認しながら置換していくのをおすすめしたい。

最後に「<blockquote 」(「<blockquote」に続けて半角スペース)を検索して、引用符に「'」を使っているところや引用符なしのところがたくさんあったら、「"」を「'」にするとか「"を含まない」を「半角スペースを含まない」にして、改めて検索・置換し直す。

</blockquote>の処理も一応考えてみた。でも上のように①②③…で説明していると長くなるし書くのも大変なので、検索・置換のセットだけ並べます。

  • 検索:^></blockquote><$
  • 置換:<<
  • 検索:^></blockquote>\n?<(.)
  • 置換:<<\n><\1
  • 検索:([^>])\n?</blockquote><?$
  • 置換:\1\n<<
  • 検索:([^>]>)\n?</blockquote><$
  • 置換:\1<\n<<

これで、検索にかかる範囲で<blockquote>タグ~</blockquote>タグは引用記法に置き換えられた。念のため「<blockquote~>」が残っていないか検索して、もしあったら必要に応じて手作業で「>>」~「<<」に書き換える。Twitterの「ツイートをサイトに埋め込む」のHTMLを書いてあると検索にかかってくるので、検索結果を一覧できるテキストエディタのほうが使い勝手がいいかも。

  1. ①「<」+②「/」(あれば)+③「blockquote」+④「 」(半角スペース・あれば)+⑤「>」(あれば)を検索
    • 検索:</?blockquote ?>?

フォトライフ記法の「:image」を「:plain」に置換(任意)

※ダイアリー内でフォトライフ記法を使っている方限定です。フォトライフ記法については→はてなフォトライフに登録した写真を表示する(fotolife記法) - はてなダイアリーのヘルプ

はてなブログでは、フォトライフ記法の「f:id:~:image」を「f:id:~:plain」にすると、画像をクリックしたとき拡大表示されるようになる。「f:id:~:image:h300」のような書き方をしていても、「f:id:~:plain:h300」のように書き直して大丈夫。「~:image」のままでフォトライフのページへのリンクにしておいてもよいが、「~:plain」に書き換えるなら以下のようにする。

(参考まで、はてなブログでは「f:id:~:image:plain」という書き方をしても「f:id:~:plain」と書いたのと同じ扱いになる。一方、はてなダイアリーでこの書き方をすると画像に続けて「:plain」という文字が出る)

「f:id:~:image」を「f:id:~:plain」にすると、はてなダイアリーでも画像は表示はされるもののはてなフォトライフへのリンクではなくなる。インポートの直前に置換するのがよいと思う。

  1. ①「f:id:」+②英数字、「_」、「-」を含む文字列+③「:」+④「yyyymmddhhmmss(数字14桁)」+⑤「b、g、j、pのいずれか」(この文字がない書き方もある)+⑥「:image」という文字列を検索して、「①②③④⑤:plain」に置換する
    • 検索:(f:id:[a-zA-Z0-9_\-\+]+:\d{14}[bgjp]?):image
    • 置換:\1:plain

ところで、はてなブログでコメントタグ(<!-- ~ -->)を含む行にフォトライフ記法があると、画像が表示されずフォトライフ記法がそのまま表示されるようだ。(フィードバック済み)

フォトライフ記法の「:movie」ははてなブログでは使えない

※2019年8月13日追記:いつの間にか「:movie」が使えるようになっていました。

→運営からの告知はなし。ただしFlashを使っているこの動画プレーヤーは将来的に廃止され、動画へのダウンロードリンクになるとのこと(→はてなフォトライフの画像アップロード画面をFlashを利用しない仕組みに変更しました。また、その他のFlashを利用している機能については廃止します - はてなフォトライフ日記 - 機能変更、お知らせなど)。以下の置換をしておくべきかは現状わかりません。(追記は以上)

※ダイアリー内にフォトライフから動画を貼り付けている方限定です。フォトライフ記法については→はてなフォトライフに登録した写真を表示する(fotolife記法) - はてなダイアリーのヘルプ

はてなフォトライフに上げた動画を表示する記法として「f:id:Imamura:20151122125034f:movie」などがある(動画アップロード機能は現在終了済み)が、これをはてなブログに書いてもなにも表示されない。「f:id:Imamura:20151122125034f:movie」の文字列も表示されない。そこでフォトライフの当該ページ(上の場合http://f.hatena.ne.jp/Imamura/20151122125034)へのリンクに書き換える。

(「[http://jp.youtube.com/watch?v=sfW2rX8IrMI:movie]」など、YouTubeなどの動画を貼り付けるhttp記法はてなブログでもそのまま表示される。ただしプレーヤーが今となってはけっこう小さめに表示される)

  1. ①「f:id:」+②英数字、「_」、「-」、「+」を含む文字列+③「:」+④「yyyymmddhhmmss(数字14桁)」+⑤「f:movie」という文字列を検索して、「[http://f.hatena.ne.jp/②/④:title=f:id:②:④f:movie]」に置換する
    • 検索:f:id:([a-zA-Z0-9_\-\+]+):(\d{14})f:movie
    • 置換:[http://f.hatena.ne.jp/\1/\2:title=f:id:\1:\2f:movie]

この置換をすると、はてなダイアリーでは動画が表示されず単なるリンクになる。こちらもインポート直前に置換するのがよいだろう。

普通の段落の改行を2つにする

※ダイアリーの本文で、段落を改行1つのみで続けて書いている方限定です

はてなダイアリーにおける改行の扱いは「段落モード」と「改行モード」の2種類ある。もともとは「段落モード」のみで、のちに「改行モード」が追加された。今は「改行モード」が初期設定である。詳しくは以下を参照。

一方はてなブログでは、編集画面での改行が1つ(段落と段落の間に空行なし)だと<br>タグが挿入され、改行2つ(段落と段落の間に空行あり)だとそこまでが<p>~</p>になる。詳しくは以下を参照。

はてなダイアリーで「段落モード」にしている人が、はてなブログでも同じように段落を<p>タグで囲んでほしい場合、段落ごとに改行を2つ入れる必要がある。一方で、リスト記法は「-」などで始まる行を連続させて書く。

そこで、まずダイアリーのテキスト全体で改行を改行×2にしてから、不要な改行を削除する方向で修正したい。「-」と「+」と「:」で始まる行が連続していたら間の改行は詰める。表の記法もあるから「|~|」という行が連続していたら改行を詰める。また「>|」で始まる行(pre記法、「>||」や「>|css|」なども含む)から「|<」で始まる行までと、「<pre>」~「</pre>」の間の改行は詰めてもいいか個別に確認する。

よく考えるとpre記法の中では行開けが大事だったりするかもしれない。あらかじめ「>\|」を正規表現で検索して、「>|」~「|<」の範囲にある改行のみの行には自分のダイアリー内で使っていない文字、たとえば「㍊」とか「㈲」などを置いておく(念のため検索し、使っていないことを確認すること)。改行を2つに増やしたあと「>|」~「|<」の範囲の改行×2を改行1つに戻し、「㍊」を削除すればいい。

  1. すべての改行を改行2つにする
    • 検索:\n
    • 置換:\n\n
  2. 「-」で始まる行が連続する場所は改行を1つに戻す(ここ以下は、2回検索/置換する。これらの行が3行以上連続するとき、1回の検索/置換では偶数行の次の余分な改行を飛ばして検索していくことがあるため)
    • 検索:^(\-.*\n)\n\-
    • 置換:\1-
  3. 「+」で始まる行が連続する場所は改行を1つに戻す
    • 検索:^(\+.*\n)\n\+
    • 置換:\1+
  4. 「:」で始まる行が連続する場所は改行を1つに戻す
    • 検索:^(:.*\n)\n:
    • 置換:\1:
  5. 「|~|」という行が連続していたら改行を1つに戻す
    • 検索:^(\|.*\|)\n\n(\|.*\|)
    • 置換:\1\n\2

日付ごとのタイトルをはてなブログへ持っていく

※ダイアリーで「日付ごとのタイトル」を書いていて、「今日の1枚」を登録していない+日記の本文を見出しで始めている方限定です

はてなダイアリーでは1日に複数のエントリを書けるほかに、日付ごとのタイトルをつけることができる。

f:id:Imamura:20190111132314p:plain

上の画像で日付の右に入力するのが、ここでいう「日付ごとのタイトル」である。

  • 仕様変更前:本文部分が見出し記法(行頭に「*」)から始まり、かつ「今日の1枚」がない場合、「日付ごとのタイトル」ははてなブログへインポートされない。
    • (「今日の1枚」を登録してあれば、タイトルが「日付ごとのタイトル」、内容が「今日の1枚」の画像というエントリがインポート時に作られる。また本文の冒頭に見出し記法を使わない文章があれば、タイトルが「日付ごとのタイトル」、本文がその文章というエントリが作られる)※この仕様は今後修正されるとアナウンスが出ている(仕様変更は「年初の予定」とされている)1月17日に修正されたと告知が出た(「はてなブログに移行した際、『今日の1枚』がエントリーの冒頭に含まれるよう変更しました - はてなダイアリー日記http://d.hatena.ne.jp/hatenadiary/20190117/1547711213
  • 仕様変更後:本文部分が見出し記法(行頭に「*」)から始まる場合、「日付ごとのタイトル」ははてなブログへインポートされない。(「今日の1枚」の有無は「日付ごとのタイトル」がインポートされるかどうかに影響しなくなった)

※ここからの内容は初出時からいったん書き換えたあと、もう一度差し替えています。参考に、この下に以前の内容も残してあります

はてダラスプリッタ向けの「diary.txt」で、日付ごとのタイトルは下のような書式で書かれている。

2010-01-01:1月1日の日付ごとのタイトル
*見出し(任意)
本文

2010-01-02:1月2日の日付ごとのタイトル
*見出し(任意)
本文

…

日付ごとのタイトルに続けてすぐ見出しがあると、日付ごとのタイトルははてなブログにインポートされない。では、日付ごとのタイトルを見出しにしたエントリを追加すればいいだろう。追加されるエントリには本文として、その日のタイトル一覧へのリンクを追加しよう。下のように検索・置換することにした。

  • ①行頭から4桁の数字+②「-」+③「0」(あれば)+④1桁か2桁の数字+⑤「-」+⑥「0」(あれば)+⑦1桁か2桁の数字+⑧「:」+⑨行末までの任意の文字列(あれば)、という文字列を検索して、見出しと本文にする
    • 検索:^(\d{4})\-(0?)(\d+)\-(0?)(\d+):(.+)$
    • 置換:\1-\2\3-\4\5:\n*t\1\2\3\4\5*\6\n\n-\1年\3月\5日の記事:(はてなブログのURL)/entries/\1/\2\3/\4\5

こうすると、日付ごとのタイトルまわりは下のように置換される。

変更前

2010-01-01:1月1日の日付ごとのタイトル
*見出し
本文

変更後

2010-01-01:
*t20100101*1月1日の日付ごとのタイトル

-2010年1月1日の記事:(はてなブログのURL)/entries/2010/01/01

*見出し
本文

日付ごとのタイトルと最初の見出しの間に本文があった場合、「-2010年1月1日の記事:(はてなブログのURL)/entries/2010/01/01」に続けて記載されることになる。

その場合の置換結果

2010-01-01:
*t20100101*1月1日の日付ごとのタイトル

-2010年1月1日の記事:(はてなブログのURL)/entries/2010/01/01

最初の見出しの前に書かれていた本文

*見出し
本文

はてなブログで日付の部分はクリックでき、たとえば「2010-01-01」なら「(はてなブログのURL)/archive/2010/01/01」というURLへのリンクになっている。リンク先はその日の記事一覧で、記事のタイトルと本文のダイジェストを読める。これはこれで便利かもしれないが、一日の記事をまとめ読みしたい向きにはうれしくない。URLが「/archive/~」ではなく「/entries/~」の場合、はてなダイアリーでいうところの「(はてなダイアリーのURL)/20100101」と同じ見た目になる。

※以下に書かれているのは最初に書いた内容です


なので、日付ごとのタイトルを書きつつ本文を見出しから始めている場合、日付ごとのタイトルを持つ見出しを本文の冒頭に作ることで、日付ごとのタイトルの内容をはてなブログへ移せることになる。

はてダラ」では、日付ごとのタイトルは「2018-01-01:日付ごとのタイトル」という形式で書く。この日付の次の行に、「*日付ごとのタイトル」という見出しをつければ、はてなブログにインポートしたとき日付ごとのタイトルがつけられる。

  1. はてダラ」の日付部分に書いた「日付ごとのタイトル」を次の行へ見出しとしてコピーする
    • ①行頭に「yyyy-mm-dd(年-月-日):」+②任意の文字列(1文字以上で行末まで)、という行を検索し、「①②[改行]*②」に置換
      • 検索:(^\d{4}\-\d\d\-\d\d:)(.+)$
      • 置換:\1\2\n*\2

※以下に書かれているのはいったん書き換えた内容です。はてなブログライターを使うかどうかにかかわらず、はてなブログは1日に投稿できるエントリが100件に制限されていることがわかったため、はてなブログ側で大量のエントリを上げる可能性がある方法はとらないことにしました

参考
1日の記事数と、1記事あたりのコメント数の制限を緩和しました - はてなブログ開発ブログ(http://staff.hatenablog.com/entry/2012/01/24/162244

「日付ごとのタイトル」ははてなブログ側に追加してもよい。今まではてなダイアリー側でいろいろしてきたのは、はてなダイアリーでつけられたブックマークやはてなスターはてなブログへ移設したいからだ。そこにこだわらなければ、「はてなブログライター」を使ってはてなブログに新規のエントリとして投稿すればよいことになる。

「日付ごとのタイトル」はもともとはてなダイアリーにないエントリだから、「はてなブログライター」と「はてなブログライタースプリッタ」ではてなブログ側に登録しよう。これらの使い方は以下を参照。

今まで検索・置換してきたテキストファイルの中から、「日付ごとのタイトル」がある日とそのタイトルを抽出する。テキストエディタGrepコマンドで以下を検索し、検索結果を別のテキストファイルに出力する。(方法はテキストエディタごとに異なるため省略)これがはてなブログライター用のテキストファイルになる。

  • 検索:^\d{4}\-\d+\-\d+:.+$

検索結果を出力したテキストファイルは以下の書式に整形する。(各行を日付+「:」+その日の日付ごとのタイトル、という内容にする)

2010-01-01:1月1日の日付ごとのタイトル
2010-01-02:1月2日の日付ごとのタイトル
…

ここから以下のように検索・置換すると、はてなブログライター向けのテキストファイルになる。「《自分のはてなブログのURL》」の部分は自分のはてなブログのURLに置き換えて置換する。

  • 検索:^(\d{4})\-(\d\d)\-(\d\d):(.+)$
  • 置換:\1-\2-\3_01:\1年\2月\3日のタイトル\ndate: \1-\2-\3 23:59:59 +0900\n\n\4\n\n-\1年\2月\3日の投稿一覧:《自分のはてなブログのURL》/archive/\1/\2/\3\n

テキストファイルの内容は以下のようになる。(「《自分のはてなブログのURL》」を「http://ima.hatenablog.jp」にした場合)

2010-01-01_01:2010年01月01日のタイトル
date: 2010-01-01 23:59:59 +0900

1月1日の日付ごとのタイトル

-2010年01月01日の投稿一覧:https://ima.hatenablog.jp/archive/2010/01/01

2010-01-02_01:2010年01月02日のタイトル
date: 2010-01-02 23:59:59 +0900

1月2日の日付ごとのタイトル

-2010年01月02日の投稿一覧:https://ima.hatenablog.jp/archive/2010/01/02

「×年×月×日のタイトル」の部分や、「-2010年01月02日の投稿一覧:~」の書き方はお好みで変えてよい。

このあとの「日ごとのエントリの順番」とも関わってくるが、はてなブログ上で日付をクリックしたとき(http://ima.hatenablog.jp/archive/2019/01/12など)には、日付ごとのエントリは一番上に出てほしい。その日のエントリ一覧ページは時刻の降順でソートされる(遅い時刻が上に来る)ので、「日付ごとのタイトル」を載せるエントリはエントリ一覧の一番上に来るよう、23時59分59秒に投稿したものとして扱う。

上のように置換されたテキストファイルを「はてなブログライタースプリッタ」にかけてから「はてなブログライター」を実行すると、それぞれの日に「日付ごとのタイトル」をタイトルに持つエントリが追加される。その日のエントリ一覧のページでは、このエントリが一番上に出る。

日ごとのエントリの順番を入れ替える

※ダイアリーで1日に複数のエントリを上げていて、見出しにタイムスタンプをつけていない=編集設定(管理-編集設定-見出しの時刻)で「見出し毎に書き込んだ時刻を:保存しない」にしている方、あるいはその設定によらず、見出しを「*t*」にしていない方限定です

1日に複数のエントリがあり、投稿時にタイムスタンプをつけていない場合(つけていても時刻の昇順――遅い時刻が下に来ている――の場合)、エントリの順序が入れ替わる。

はてなダイアリーで、ある日のエントリとして下のように書いていたとする。

*最初のエントリ
最初のエントリの内容

*2つめのエントリ
2つめのエントリの内容

*3つめのエントリ
3つめのエントリの内容

これをはてなブログへインポートすると、はてなブログのトップページや日付をクリックして行く「(はてなブログのURL)/archive/2019/01/01」のようなURLでは下のような表示順序になる。

*3つめのエントリ(00:00:02に投稿されたものとして扱われる)
3つめのエントリの内容

*2つめのエントリ(00:00:01に投稿されたものとして扱われる)
2つめのエントリの内容

*最初のエントリ(00:00:00に投稿されたものとして扱われる)
最初のエントリの内容

こういうふうになるのは、たぶん以下の2点の考え方に基づくためだろう。

  • はてなダイアリーで同じ日に複数のエントリを書く場合、その日の末尾へ追加していったと想定している
  • はてなブログは新しいエントリほど上に来るようにソートされる

はてなダイアリーでタイムスタンプをつけて投稿(そう設定するか見出しを「*t*」で始める)していて、かつその日の新しいエントリは上へ上へと追加していた場合、はてなブログへインポートしてもエントリの順序は変わらない。しかしそれ以外のケースでは、エントリの見た目の順序が入れ替わることになる。

「(はてなブログのURL)/entries/2019/01/01」のようなURLへ行くと表示順序が変わり、下のようになる。

*最初のエントリ(00:00:00に投稿されたものとして扱われる)
最初のエントリの内容

*2つめのエントリ(00:00:01に投稿されたものとして扱われる)
2つめのエントリの内容

*3つめのエントリ(00:00:02に投稿されたものとして扱われる)
3つめのエントリの内容

これははてなダイアリーで日付をクリックして行く「(はてなダイアリーのURL)/20190101」のようなページの見た目と同じになる。いいねー。だがしかし、はてなブログのページ上にはこのURLへ行くリンクが自動生成されない。じゃあやっぱり、はてなダイアリー側でエントリの順序を入れ替えてからインポートした方がよさそうだ。

以下のようにして、はてなダイアリーの側でエントリの順序を入れ替えた。これをはてなブログにインポートすると、はてなダイアリーのもとの順序でエントリが表示されることになる。

ただし、下のスクリプトはコメント(<!-- ~ -->)の範囲に見出しがあるとうまくいかない。見出しがコメントの範囲にあるかどうかをチェックしていないからだ。そこだけ気をつけて使って下さい。

  1. 「diary.txt」と同じディレクトリに下のスクリプト「reverse_addheader.pl」を置く
  2. 「diary.txt」の見出しの先頭に、ダイアリー内に出てこない文字を(ここでは「㈲」)を追加する
    • 検索:^(\*[^\*])
    • 置換:㈲\1
  3. 「diary.txt」の文字コードを「reverse_addheader.pl」と同じにして保存(どちらもUTF-8に揃えるのが問題が起きなさそう)
  4. はてダラスプリッタ(hws.pl)を実行
  5. 「diary.txt」は名前を「diary_bak.txt」などに変えて取っておく
  6. 「dir /b ????-??-??.txt > reverse.bat」を実行
  7. 「reverse.bat」をテキストエディタで開く
  8. 「reverse.bat」の内容を正規表現で以下のように置換
    • 検索:^(.)
    • 置換:perl reverse_addheader.pl \1
  9. 「reverse.bat」を実行
  10. 「copy a????-??-??.txt diary.txt」を実行
  11. 「diary.txt」をテキストエディタで開き、文字コードを「ShiftJIS(シフトJIS)」に変更
  12. (お好みで)「\n\n\n」を「\n\n」に一括置換(検索されなくなるまで複数回行う)

これで、ダイアリーはその日のエントリの順序が逆になった。この状態からはてなブログへインポートすれば、はてなダイアリーでの以前の見た目に近くなる。

reverse_addheader.pl

#! /usr/local/bin/perl

foreach $infilename ( @ARGV ){ #コマンドラインで指定された複数の引数をすべて処理する(引数は@ARGVを通して$infilenameに入る)
	$day = $infilename;
	$day =~ s/([\d\-]+)\.txt/\n$1:/g; #■「2001-01-01.txt」を「<改行>2001-01-01:」に(各テキストファイルの末尾に改行がないことがあるので念のため)
	$outfilename="a".$infilename; #■「a元ファイル名」というファイルに出力

	open(IN,"$infilename");
	open(OUT,"> $outfilename");
	while (<IN>) {#<IN>に入力されたファイルを処理する
		$out = $out . $_; #いったん全部の行をまとめて入れる(改行を含む置換をしたいから)
	}

	@txt = split(//, $out);
	$txt[0] = $day . $txt[0];
	@txt[$#txt+1] = $txt[0]; #■配列の末尾に配列の先頭をコピーする(その日のタイトルはエントリの順序を入れ替えても先頭に来るようにするため)
	shift(@txt); #■配列の先頭を削除する
	@reversetxt = reverse(@txt); #■配列の要素を逆順にする

	foreach $out (@reversetxt){
		print OUT $out;
	}

	close IN;
	close OUT;
}

Perlスクリプトを使わない方法(※記事が多いと大変ですが)

はてなブログのエントリはすべて投稿時刻の情報を持っている。はてなダイアリーでタイムスタンプをつけずに投稿したエントリでも、はてなブログへインポートされると仮の時刻情報が付与される。

はてなダイアリーで下のように書いていた日があるとする。

*最初のエントリ
最初のエントリの内容

*2つめのエントリ
2つめのエントリの内容

*3つめのエントリ
3つめのエントリの内容

これをはてなブログへインポートすると、以下の時刻情報が付加される。

  • 最初のエントリ:その日の00:00:00
  • 2つめのエントリ:その日の00:00:01
  • 3つめのエントリ:その日の00:00:02

はてなダイアリーはてなブログへインポートしたあと、ダイアリーからインポートしたエントリの投稿時刻をはてなブログ側で変更することもできる。時刻を変更したいはてなブログのエントリをブラウザで開いて「編集」ボタンをクリックし、ウィンドウ右側の歯車アイコンから「投稿日時」を編集すればよい。入力欄にもともと入っているのが「00:00」のように「時:分」のみの書式だった場合でも、「00:00:01」のように秒つきで入力できる。

上に来てほしいエントリを遅い時刻にすれば、ダイアリー時代のはてなブックマークはてなスターを維持したまま表示順序を変えられる。投稿時刻を変更したらウィンドウ左下の「更新する」ボタンをクリックすればよい。

各記事の投稿時刻は、たとえば下のようにする。

  • 最初のエントリ:その日の00:02:00
  • 2つめのエントリ:その日の00:01:01
  • 3つめのエントリ:その日の00:00:02

全部手作業なので記事が多いと大変だが、これならPerlスクリプトなどを使わなくてもよい。

追記:リンクのhref属性にid記法などを書いても展開されない

先ほど、タグ内の「href」「cite」「src」属性値に[id:~][ISBN:~][google:~]といった記法を利用できるよう変更しましたので、aタグを利用してご指定ください。

<a href="google:はてな" title="がーぐるはてな">はてな(がーぐる)</a>
<a href="id:jkondo" title="スタッフ日記">スタッフ日記</a>の方も更新しなくちゃ

と記入すると、

はてな(がーぐる)

スタッフ日記の方も更新しなくちゃ

と表示されます。

リンクのタイトル、文字列指定 - はてなダイアリー日記

はてなブログではこの書き方は使えなくなっていて、単に「google:はてな」などのURLへジャンプしようとしてNot Foundになる。

「[http://www.google.com/search?q=%E3%81%AF%E3%81%A6%E3%81%AA&ie=utf-8&oe=utf-8:title=はてな(がーぐる)]」といった書き方に変換する。

リンクのhref属性にURL以外を書いている場所を探すには、正規表現で「 href=["']?[^"'h]」を検索すればよい。(この記事の上のほうで拡張id記法http記法に置き換えていると、「<a href="id:Imamura:20030217:p1">よろしくお願いします</a>」が「<a href="[http://d.hatena.ne.jp/Imamura/20030217/p1:title=id:Imamura:20030217:p1]">よろしくお願いします</a>」なんてなっちゃっていかにもヨクナイ)

下のようなPerlスクリプトで、「out.txt」に「[http://www.google.com/search?q=%E3%81%AF%E3%81%A6%E3%81%AA&ie=utf-8&oe=utf-8:title=はてな]」が出力される。

#! /usr/local/bin/perl
use Encode qw(encode_utf8);

$org = "はてな"; # 変換したい文字列
($str = $org) =~ s/([^ 0-9a-zA-Z])/"%".uc(unpack("H2",$1))/eg;
$str =~ s/ /+/g;
$out = "[http://www.google.com/search?q=" . $str . "&ie=utf-8&oe=utf-8:title=" . $org . "]";
open(OUT, ">> out.txt");# 「>>」を「>」にすると実行のたびに追記されずout.txtの内容が置き換えられる
print OUT ($out ."\n");
close OUT;

(もっとちゃんとやればより多くのパターンに対応できる)

はてダラが途中で止まるときは

「diary.txt」の修正が終わったら「はてダラスプリッタ」で日付ごとのテキストファイルに分解し、「はてダラ」ではてなダイアリーに投稿する。

はてダラ」を実行すると「Post 2019-01-01.」「Post OK.」「Post 2019-01-02.」「Post OK.」…とゆっくり表示が出て、はてなダイアリーに記事が投稿されていく。更新した日がすごく多いと、途中で「ERROR: Post: Unexpected response: 502 Bad Gateway」といったエラーを出して止まってしまうことがある。ここで「はてダラ」を再実行すると、更新された日のダイアリーをまた最初から投稿し直すことになり効率が悪い。「Post OK.」と出た日までのテキストファイル(「2019-01-01.」なら「2019-01-01.txt」)をいったん別のフォルダに移してから「はてダラ」を再実行すれば、投稿されていない日付が処理されていく。すべての日を投稿できたら別のフォルダから戻せばよい。

エラーを出して止まった日付は「Post OK.」になっておらずまだ投稿されていないので、そこだけ気をつける。

これでよし

のはず。ふー、お疲れさまでした。書き換えられたはてなダイアリーはてなブログにインポートしよう。

はてなダイアリーはてなブログの仕様は実にいろいろ異なっていて、単なるインポートではあちこち問題が出てしまう。ここまでの検索・置換でけっこういい感じに修正できたと思うけれどこれでも見落としがあるかもしれない。「この書き方がはてなブログでは再現されない」というのがほかにあったらご指摘ください。

テストのため、以前書いていた「まんぷく::日記」をはてなブログへインポートしてみた。リダイレクトはまだ設定していないので、はてなダイアリーの側も今のところ見ることができる。両者で見た目がどう変わるかの確認にどうぞご利用ください。

もとのはてなダイアリー
d:id:manpukuya
上をインポートしたはてなブログ
https://manpukuya.hatenablog.jp/

このはてなブログのデザインは「Palette」にしてみた。

あとはトラックバックを移籍したい。はてなダイアリーの全部の月のHTMLを取得して、そこから抽出するしかないかな。

はてなブログをテキストファイルから更新する方法

はてなダイアリーを「diary.txt」から更新するように、はてなブログもテキストファイルを編集する方法で更新したい。

はてなブログライター」でエントリを登録するとテキストファイルの修正でエントリを修正でき、「はてなブログライタースプリッタ」を使うと「はてなブログライター」で登録したエントリを一括で修正できる。詳しくは以下のエントリを参照。