Google Analytics タグを外部ファイル化する方法(Perl 正規表現)

Google Analytics のレガシータグを、外部 JavaScript の読み込みに変更する方法。Perl のワンライナーを使ってさくっと行えます。

Google Analytics タグの管理

Webサイトのアクセスログ分析のために追加する Google Analytics タグ(スニペット)は「この <script> タグを全ページに貼り付けて下さい。」という事になっている。

これは結構面倒な上にファイルは大きく、分かりにくくなるし、時々仕様が変わって新しいタグに変わったりするので厄介だ。
という事で、 Google Analytics タグは外部ファイル一つにまとめて以下のようなコードで読み込むのが便利です。

※ この時、ファイルに記載する内容からはスニペットの HTMLタグ部分、つまり <script> と </script> は削除します。

<script type=”text/javascript” src=”/js/ga.js”></script>

Google Analytics レガシータグから <script> タグへの変換方法

これからサイトを作る場合は、サイト共通の JavaScript ファイルを作って(サイト共通のCSSファイルを作るのと同じ発想)、そこに Google Analytics のタグも入れておけばよいのですが、既に各ページに Google Analytics タグを仕込んでいる場合、サイト共通の JavaScript ファイルがあってもそこに追加してしまうと JavaScript コードが重複してしいます。このため、既存のコードを削除するか、または 上のようなタグに置換する必要があります。

これを、Perl のワンライナーでさくっと行う方法のご紹介です。

基本の Perl ワンライナー

例えば、同じディレクトリにある index.html の Google Analytics タグを変換したい場合は以下のように実行します。

Google Analytics レガシータグ を 外部ファイルを読み込む <script> タグに書き換える場合

perl -0777 -npi.bak -e \
‘s{<script[^>]*>\s*var gaJsHost[^<>]*?</script>\s*<script[^>]*>[^<>]*?</script>}{<script type=”text/javascript” src=”/js/ga.js”></script>}is’ \
index.html

Google Analytics レガシータグ を削除する場合

(サイト共通の JavaScriptファイルが既にありそれを利用する場合など。)

perl -0777 -npi.bak -e \
‘s{<script[^>]*>\s*var gaJsHost[^<>]*?</script>\s*<script[^>]*>[^<>]*?</script>}{}is’ \
index.html

解説

-n は「ファイルを(1行ずつ)読み込んで処理する」、-p は「読み込んだ内容を出力する」、-e は「読み込んだ内容に対する処理」、-i は出力で元のファイルを置き換える、その後の「.bak」はバックアップファイルの拡張子です。

ポイントは、「-0777」というオプションを付ける点で、このオプションは、「-n」の「1行ずつ」という規則を変えて、ファイル全体を一気に読み込んで処理できます。(具体的には、改行がレコードの区切りである、という前提をリセットしてこれを実現しています。)

-e の内容は Perl の文法に従って色々な表記が省略されていますが、ファイル内容を置換する場合、このままイディオムとして覚えてしまうと楽です。
複数行の置換をしますので、正規表現のオプションとして 「s」を付けます(末尾についている「s」)。なお、「is」の「i」の方は case Insensitive (大文字小文字を区別しない)オプションです。古い HTML ファイルを扱うような場合は付けて置いた方がよいでしょう。

Perl のワンライナーでファイル内容の置換を行う時の正規表現指定方法

慣れてないとくらくらすると思いますが、置換設定の構造は以下の通りです。

-e ‘s{置換ターゲット正規表現}{置換後文字列}is’

コード一括置換のための作業手順ベストプラクティス

以下の通り作業すると、おそらく冷や汗ものの失敗をしないで一括置換ができます。

1ファイルテスト置換

まず、1ファイルの置換を試して正規表現が問題ないか確かめます。

perl -0777 -npi.bak -e \
‘s{<script[^>]*>\s*var gaJsHost[^<>]*?</script>\s*<script[^>]*>[^<>]*?</script>}{<script type=”text/javascript” src=”/js/ga.js”></script>}s’ \
index.html

結果確認

diff で結果確認。

diff index.html.bak index.html

変換を戻しておく

OKだったら、一旦変換したファイルを戻しておきます。
こうしておくことで、後での一括置換がうまく行かなかった時に、このファイルがうまく行ったかどうかで、正規表現以外の部分で問題があったのかという事を簡単に知る事ができます。

mv index.html.bak index.html

OK ならディレクトリをバックアップ

対象ディレクトリの上に移動して、一応バックアップを取っておきます。
(バージョン管理システムなどがあるなら不要。)

cp -r targetdir backupdir

一括置換

今度は、バックアップファイル(.bak)を作成せずに置換を行います。

cd targetdir

find . -name “*.html” \
| xargs grep -l gaJsHost \
| xargs -l perl -0777 -npi -e \
‘s{<script[^>]*>\s*var gaJsHost[^<>]*?</script>\s*<script[^>]*>[^<>]*?</script>}{<script type=”text/javascript” src=”/js/ga.js”></script>}s’

結果確認

結果を確認します。
意図しない変換がされたファイルがあれば、backupdir から引き戻します。

cd ..
diff -Bbr backupdir targetdir | less

コード置換部分の解説

上のサンプルコードは何をやっているかというと、

find . -name “*.html” \
| xargs grep -l gaJsHost \
| xargs -l perl -0777 -npi -e \
‘(置換の正規表現)’

1行目では、まず .html ファイルだけを選択。

2行目で、その中で「gaJsHost」というキーワードが含まれているファイルだけを探しています。grep の -l オプションは、デフォルトの出力を抑え、マッチしたファイル名だけを出力してくれます。

3行目ではそのファイル名をさらに先ほどの Perl ワンライナーの処理対象としています。xargs の -l オプションは、何ファイルごとに引数として 次のコマンドに渡すかの指定です。指定しなければ一気にファイルリストを perl コマンドに送ってしまうので、最初の1ファイルしか変換ができません。-l オプション数字なしで指定すると、1ファイルずつ perl 側に送ってくれます。

補足

以下のように find の -exec オプションで即 置換をしてもいいのですが、何かと対象外にするファイルがあったり、または全く処理する必要のないファイルもあったりするので、”xargs grep” でパイプしながら、最後に “xargs -l perl …” で処理する方がよいと思います。

find から直接 perl にコマンドを渡す場合

find . -name “*.html” -exec \
perl -0777 -npi -e ‘(置換の正規表現)’ {} \;

カスタム変数を設定しているページは一括置換から除く例

例えば、レガシータグを設定しているファイルのうち、特別な設定(例えばカスタム変数を設定しているページ)は一括の置換から除いて後で手動で処理したいとします。

この場合は以下のように、パイプをつなげて行くことでファイルの選択ができます。grep -L は指定した表現にマッチする行が無かったファイルを出力します。

find . -name “*.html” \
| xargs grep -l gaJsHost \
| xargs grep -L _setCustomVar \
| xargs -l perl -0777 -npi -e \
‘(置換の正規表現)’

Google Analytics レガシータグ を探す正規表現の作り方

Perl の正規表現に関するおまけ解説。

置き換えのターゲットとするコードは以下のようなものなので、

<script type=”text/javascript”>
var gaJsHost = ((“https:” == document.location.protocol) ? “https://ssl.” : “http://www.”);
document.write(unescape(“%3Cscript src='” + gaJsHost + “google-analytics.com/ga.js’ type=’text/javascript’%3E%3C/script%3E”));
</script>
<script type=”text/javascript”>
var pageTracker = _gat._getTracker(“UA-xxxxxx-1”);
pageTracker._trackPageview();
</script>

正規表現は以下の2つの条件でマッチさせます。

  • <script>タグが2つ続いている
  • 最初の<script>タグの冒頭に「var gaJsHost」が現れる

「<script> と </script>の間の全ての文字列」は

[^<>]*?

という正規表現でマッチさせることができます。

開始タグ内で属性の記載があっても無くてマッチさせたい部分は

[^>]*

でを指定します。

結果、以下の様な指定になります。

‘s{<script[^>]*>\s*var gaJsHost[^<>]*?</script>\s*<script[^>]*>[^<>]*?</script>}{置換後文字列}is’