CDATAセクションを正しくエスケープする方法

<![CDATA[(ここ)]]>

(ここ)は確かにHTMLエスケープしなくてもいいんだけど、(ここ)に予期せぬ"]]>"が現れるとそこでCDATAセクションが終わってしまう。


だから(ここ)に"]]>"という字面が現れないようにしないといけないので、

全ての
]]>
を
]]]]><![CDATA[>
に置き換える。


分断の仕方によって他にも書き方があって、パターンは以下の通りになる。

]]]]><![CDATA[>
]]        ]]>            <![CDATA[      >
↑"]]"    ↑CDATA終了    ↑CDATA開始    ↑">"

]]]>]<![CDATA[>
]        ]]>            ]      <![CDATA[      >
↑"]"    ↑CDATA終了    ↑"]"  ↑CDATA開始    ↑">"

]]]><![CDATA[]>
]        ]]>            <![CDATA[      ]>
↑"]"    ↑CDATA終了    ↑CDATA開始    ↑"]>"

]]>]]<![CDATA[>
]]>            ]]        <![CDATA[      >
↑CDATA終了    ↑"]]"    ↑CDATA開始    ↑">"

]]>]<![CDATA[]>
]]>            ]        <![CDATA[      ]>
↑CDATA終了    ↑"]"    ↑CDATA開始    ↑"]>"

どれが一番美しいだろうか?
私ならギリギリまで粘るという意味で、]] と > に分けるかな。
見た目のかっこ良さからいうと3番目かも。バランスは一番良いよね。

vimのsyntax highlightが美しくて分かりやすかったのでスクショ撮ってみた。

一応上記以外に以下のようなパターンがあるけど、

]]>]]&gt;<![CDATA[

"&gt;"が美しくないので、>は必ず次のCDATAセクションに入るようにしてる。
(意味的には「"]]>"をCDATAセクションに入れない」となって美しいんだけどね)

MySQLで縦型を横型に(擬似)変換する(GROUP BYでも全ての値を取り出す)方法

普通GROUP BYしたときには、まとめられたレコードのうちどれか1レコードだけが取れます。
GROUP_CONCATを使うと、1レコードではなくて全レコードを連結した値を取り出せます。

MySQL :: MySQL 5.6 リファレンスマニュアル :: 12.19.1 GROUP BY (集約) 関数
マニュアルには、生徒の名前でGROUP BYして、テストの点数をカンマ区切りで取り出す例が載ってます。

で、GROUP_CONCATはGROUP BYしなくても使えます。

SELECT c1 from t1;
+----+----+
| c1 | c2 |
+----+----+
| 1  | a  |
| 2  | b  |
| 3  | c  |
+----+----+
SELECT GROUP_CONCAT(c1), GROUP_CONCAT(c2) from t1;

これでカラムc1の全ての値がカンマ区切りで取得できます。

+------------------+------------------+
| GROUP_CONCAT(c1) | GROUP_CONCAT(c2) |
+------------------+------------------+
| 1,2,3            | a,b,c            |
+------------------+------------------+

(動かしてないけど多分動くと思います・・・。動かなかったらごめん)

プロジェクト内のファイルをいちいちfindしなくて済むようにlocateする

プロジェクトが大きくなるとfindが重くなるので、locate使いましょう。で、ちょっと困ったこともあるのでその話も。

まずupdatedbでファイル一覧のデータベースを作っておきます。

$ project=/path/to/project ; \
updatedb \
--output=${project}.db \
--require-visibility no \
--database-root=${project} \
--prunepaths="$(find ${project} -name .svn)"

出力は/path/to/project.dbにしてるけど別にどこでもいいです。
Subversion使ってるプロジェクトだと、各ディレクトリに.svnがあるので--prunepathsで全ての.svn以下を無視させてる。
chgrpされて一般ユーザーではエラーが出る場合があるけど、その場合は--require-visibility noしておくととりあえず動く。

このupdatedbを定期的にcronで回しておけば良い。


あとは実際に検索するだけ

$ locate --database=${project}.db '探したいファイル名(の一部でもいい)'

自分は正規表現で指定するのが好きなので

$ locate --database=${project}.db --regexp='探したいファイル名の正規表現'


で、困ったことなんだけど、updatedb (mlocate) 0.15

  • .svnそのものが残る

locateしたときに.svnディレクトリそのものが引っかかってしまう。
まぁこれは百歩譲って良いとして、

  • --prunepathに「-(ハイフン)」が入ってるディレクトリを指定しても無視されない!

これはかなり嫌。例えば--prunepathに/foo-bar/.svnを指定しても、/foo-bar/.svn/entriesなどがlocateで引っかかってしまう。

とりあえずlocateの検索結果をフィルタリングする方法で凌いでる。
誰か解決策知らないかなー?バージョン上げたらいいよ!とかパッチがあるよ!とかパッチ書くよ!とか大歓迎!
(ホントに気が向いたら自分でパッチ書くけど…)

Re: .emacs分割のすゝめ | tech.kayac.com - KAYAC engineers' blog

.emacs分割のすゝめ - KAYAC engineers' blog
init-loader使うのもいいんだろうけど、もっと手軽に

;; 環境毎のファイルは1個で十分
(load (locate-user-emacs-file (prin1-to-string window-system)))
;; 分割ファイル読み込み(~/.emacs.d/init.d/*.elに置いておく)
(let* ((dir (locate-user-emacs-file "init.d/"))
       (el-suffix "\\.el\\'")
       (files (mapcar
               (lambda (path) (replace-regexp-in-string el-suffix "" path))
               (directory-files dir t el-suffix))))
  (while files
    (load (car files))
    (setq files (cdr files))))

ってしてる。特にこれで困ったことは無い。


環境毎のファイルについては以前書いてた→window-system毎のファイルを用意する場合の読み込み方について - ヒルズで働く@robarioの技ログ

vimで、設定系ファイルを特に修正すること無くfolding(折り畳み)する方法

こんにちわ!今日も元気に折り畳んでますか?

設定系のファイルはこんな感じになっていることが多いですよね。

# コメント
abc
def

# コメント2
# コメント2−1
foo
bar

これをvimで元気に折り畳みたいけど、いちいち{{{とか}}}とか書くほどの元気は無いので、以下のコードをファイル冒頭に書いてみたら

# vim:set foldmethod=expr foldexpr=getline(v\:lnum-1)!~'^#'&&getline(v\:lnum)=~'^#'?1\:getline(v\:lnum+1)=~'^\\s*$'?'<1'\:'=' :


こんな感じになって

+--  3 行:# コメント--------------------------------------------------------------------------------------------------------------

+--  4 行:# コメント2------------------------------------------------------------------------------------------------------------

元気が出た。





foldexprのコードが元気出ない感じなので、誰か添削してください。

クラスメンバの記述順序に依存してしまう書き方と、依存させない方法

まぁちょぃとこのコードを見てください。クラスメンバで定数を定義して、クラスメンバでそれを代入するコードです。

package {
    import flash.display.*;
    public class Main extends Sprite {
        private const constant:Object = {};
        private var variable:Object = constant;

        function Main() {trace(variable);}
    }
}

これ、何が出力されるでしょう?正解は[object Object]です。
では、こちらは何が出力されるでしょう?メンバの順序を入れ替えただけです。

package {
    import flash.display.*;
    public class Main extends Sprite {
        private var variable:Object = constant;
        private const constant:Object = {};

        function Main() {trace(variable);}
    }
}

正解はnullです。まぁ何らかのclass-based OOP言語をやった人なら分かると思いますが、
variableに代入する時点ではconstantが初期化されてないわけですね。



ところで、constメンバをインスタンス変数にしておく理由はないので普通はstaticにします。(参考までにwonderfl build flash online | 面白法人カヤック

         private var variable:Object = constant;
-        private const constant:Object = {};
+        private static const constant:Object = {};

この状態なら、variableを先に書いても問題無いですね。インスタンス変数より静的変数の方が先に初期化されますから。
しかし、だからと言って

-        private var variable:Object = constant;
+        private static var variable:Object = constant;
         private static const constant:Object = {};

なんてことをしてどちらもstaticにしてしまうと、また順序に依存するようになってvariableの方を先に書くとnullになってしまいます。
スコープが同じなので記述順序がそのまま初期化順序になってしまうからですね。



こういう記述順序に依存しないためにはどうすればいいのかなー。
で、とりあえず思いついた案は別クラスに外出しすること。

package {
    import flash.display.*;
    public class Main extends Sprite {
        private static var variable:Object = MainConst.constant;

        function Main() {trace(variable);}
    }
}
/* MainConst.as */
package {
    class MainConst {
        public static const constant:Object = {};
    }
}