2008-02-07 [長年日記]
λ. 正規表現における非包含オペレータの提案 by 田中哲
を読んだ。天泣記 (2008-01-11) より。いつもながらakrさんのこういうセンスは羨ましい。
これが役に立つ例はいくらでもあるとは思うが、最近遭遇したものだと「プレーンテキストをHTMLに変換する際にURLをアンカーにする」処理が直観的に書けそうだと思った。
実際に書いたコード:
def text2html(s) re = URI.regexp result = '' while m = re.match(s) result << CGI.escapeHTML(m.pre_match) uri = CGI.escapeHTML(m.to_s) result << %Q[<a href="#{uri}">#{uri}</a>] s = m.post_match end result << CGI.escapeHTML(s) result end
非包含オペレータがあるとこう書けそう:
def text2html(s) s.gsub(/(#{URI.regexp})|!(?:#{URI.regexp})/) { if $1 uri = CGI.escapeHTML($1) %Q[<a href="#{uri}>#{uri}</a>] else CGI.escapeHTML($2) end } end
おまけにtDiaryのString#make_linkのコード。 スペースやタブの処理もあるので単純に比較はできないけど、なんというか……
class String def make_link r = %r<(((http[s]{0,1}|ftp)://[\(\)%#!/0-9a-zA-Z_$@.&+-,'"*=;?:~-]+)|([0-9a-zA-Z_.-]+@[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+\.[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+))> return self. gsub( / /, "\001" ). gsub( /</, "\002" ). gsub( />/, "\003" ). gsub( /&/, '&' ). gsub( /\"/, "\004"). gsub( r ){ $1 == $2 ? "<a href=\"#$2\">#$2</a>" : "<a href=\"mailto:#$4\">#$4</a>" }. gsub( /\004/, '"' ). gsub( /\003/, '>' ). gsub( /\002/, '<' ). gsub( /^\001+/ ) { $&.gsub( /\001/, ' ' ) }. gsub( /\001/, ' ' ). gsub( /\t/, ' ' * 8 ) end end