Edited at

Rubyのワンライナーを使って、HAMLの%img{ }をimage_tagに置換する方法

More than 5 years have passed since last update.


このTipsが必要になる背景


  • デザイナーさんが画面デザインをHTMLで納品してくれる場合がある。

  • RailsプログラマとしてはHAMLで書き直したい。

  • 大方のタグは Html2Hamlで自動変換できる。

  • しかし、画像はassetsの下に置くのでパスが変わってしまう。


  • %img{ }は全部image_tagメソッドを使って書き直したいが、数が多いので手作業でやるのは面倒。


やりたいこと

こんなimgタグを

%img{alt: "顔写真", height: "80", src: "img/face.jpg", width: "100"}

こう置換したい。

= image_tag "face.jpg", size: "100x80", alt: "顔写真"


解決策

Rubyのワンライナーで置換してみた。

$ ruby -pe 'sub(/%img{alt: "([^"]+)", height: "([^"]+)", src: "img\/([-\w.]+)", width: "([^"]+)"}/, "= image_tag \"\\3\", size: \"\\4x\\2\", alt: \"\\1\"")' test.html.haml > replaced.html.haml


実行例


test.html.haml

%body

%img{alt: "顔写真1", height: "80", src: "img/face-1.jpg", width: "100"}
%hr
%img{alt: "顔写真2", height: "100", src: "img/face-2.jpg", width: "120"}
%p

$ ruby -pe 'sub(/%img{alt: "([^"]+)", height: "([^"]+)", src: "img\/([-\w.]+)", width: "([^"]+)"}/, "= image_tag \"\\3\", size: \"\\4x\\2\", alt: \"\\1\"")' test.html.haml > replaced.html.haml


replaced.html.haml

%body

= image_tag "face-1.jpg", size: "100x80", alt: "顔写真1"
%hr
= image_tag "face-2.jpg", size: "120x100", alt: "顔写真2"
%p


解説

コマンドがややこしく見えると思うので解説します。


コマンドの基本形

ruby -pe 'sub(/正規表現/, "置換後の文字列")' 処理対象ファイルのパス > 置換後のファイルパス というのがこの処理の基本形。



  • -eオプションはワンライナーを実行する。


  • -pオプションはファイルの内容を1行ずつ読み取る。


  • subは読み取った行のテキストを置換する。


  • 処理対象ファイルのパスでRubyに食わせるファイルを指定する。

  • 最後に、> 置換後のファイルパスという形で標準出力の内容を新しいファイルに書き込む。これを省略すると標準出力に置換後の文字列が表示される。動作確認するときに便利。


subの処理

subの処理については以下の通り。



  1. 正規表現で各値をキャプチャする。


    • /%img{alt: "([^"]+)", height: "([^"]+)", src: "img\/([-\w.]+)", width: "([^"]+)"}/




  2. 各値は以下のような番号でキャプチャされる。(丸括弧がキャプチャ用のメタ文字)


    • alt: \1

    • height: \2

    • src: \3 (ただしimg/は含まない)

    • width: \4



  3. キャプチャした文字列を利用して、置換後の文字列を組み立てる。


"= image_tag \"\\3\", size: \"\\4x\\2\", alt: \"\\1\""


制限事項&備考


  • あくまで、altやheightなどの属性が同じ順番で並んでいることが前提です。順番が違ったり、存在する属性としない属性がバラバラだったりすると正規表現にマッチしません。

  • そこそこの努力で80点ぐらいの結果が出せることを目的としています。

  • 一発で完璧にマッチする正規表現を作るのは難しいので、http://rubular.com で試行錯誤した方が近道だったりします。


応用

CSS(SCSS)のurlimage-urlに置き換えてみましょう。


test.css.scss

body {

text-align: center;
background: url("../img/bg.jpg") no-repeat center top #f8f8f8;
}

#headWrapper {
background: url("../img/head_bg.jpg") repeat-x right top;
height: 80px;
}


$ ruby -pe 'sub(/url\(.?\.\.\/img\/([-\w.]+).?\)/, "image-url(\"\\1\")")' test.css.scss > replaced.css.scss


replaced.css.scss

body {

text-align: center;
background: image-url("bg.jpg") no-repeat center top #f8f8f8;
}

#headWrapper {
background: image-url("head_bg.jpg") repeat-x right top;
height: 80px;
}



参考文献


おまけ:「そもそも正規表現がわからないんですけど?」というプログラマさんへ

それはマズいです!!今すぐ勉強してください!

正規表現をマスターすればあなたの生産性は256倍向上します。

僕はオライリーの「フクロウ本」で勉強しました。

一見、難しそうな本に見えますが、基本の「キ」から丁寧に教えてくれるので非常にわかりやすかったです。

詳説 正規表現 第3版



51cRxtwo7IL._SL160_.jpg