【Mac(Linux)】複数のファイルの先頭に文字列を追加する

最近、複数の静的HTMLファイルにスクリプトを追加する機会がありました。

静的ファイルが少なければ、一個一個ファイルを開いて、指定の場所にタグをコピーする方法で作成する方法で事足ります。
一見単純作業に思えますが、ファイル数が多い場合はかなり時間と労力を取られます。

さて、
今回はシェルスクリプトでタグの挿入をするスクリプトを作り、複数のファイルに対して一気に置換を行う方法について触れます。

目次

今回のファイル構成について

例えば、下記のようなファイル構成のサイトがあったとします。
サイズ毎にディレクトリ訳されていて、配下にphpファイルが置かれています。

items
    - l_size
         - item_1.php
         - item_2.php
         - item_3.php
    - m_size
         - item_1.php
         - item_2.php
         - item_3.php
    - s_size
         - item_1.php
         - item_2.php
         - item_3.php

ファイルの中身について

格納されているphpファイルのタグは下記のようになっているとします。
bodyタグ配下にはdata-src属性があり、これはページ毎に違います。

<?php
<head>
</head>
<body>
      //.. 省略
     <div data-src="(個別の情報)"></div>
</body>

今回実装する指針

今回作成するスクリプトの目的は、先頭に新しいphpスクリプトタグと処理を追加します。
また、ページ内にあるページの個別の情報をスクリプト内で引用できるようにします。

置換イメージ

今回は個別の情報をechoで出力できるようにします。
また、取得元が静的な状態ですので、変数から取得できるようにします。

<?php
// 新しいスクリプトを追加
$pageValue = (個別の情報);
echo($pageValue);
?>
<?php
<head>
</head>
<body>
      //.. 省略
     <div data-src="<?= $pageValue ?>"></div>
</body>

シェルスクリプト

下記のようなスクリプトファイルを作成します。   仮にファイル名をinsertScript.shとします。

#!/bin/bash

# itemsディレクトリを再起的に検索して、phpファイルに対して同じ処理を加える  
for file in `find ./items/**/*.php -type f`; do

         # data-src属性の行を探し、sedで属性の中身のみを抽出
    PAGE_VALUE=`grep 'data-src' ${file} | sed -e 's/.*data-src=\"\(.*\)\".*/\1/'`
        
        # 複数行になるためヒアドキュメントでスクリプトを取得
    HEAD_TEXT=$(cat <<EOF
<?php\\n\
\$pageValue = "${PAGE_VALUE}";\\n\
echo(\$pageValue);\\n\
?>\\n
EOF
)

        # ファイルの先頭にスクリプトを追加
    sed -i '' "1s/^/${HEAD_TEXT}/" ${file}

        # 動的に変えられるように、data-srcの属性はスクリプトタグに変更
    sed -i '' 's/\(.*\)data-src=\"\(.*\)\"\(.*\)/\1data-src=\"<\?= \$pageValue \?>\"\3/g' ${file}
done

上記で作成したスクリプトを、itemsディレクトリと同じ階層に設置します。
設置した状態でシェルを実行すれば、複数のファイルを一括置換できます。

$ bash insertScript.sh

注意事項

主に、ヒアドキュメントを変数に入れる際の注意事項です。

ヒアドキュメントを書く場合は、インデントを含められない

下記(便宜上、<--->で表記)のように、インデントを入れてしまうと構文エラーになります。

    HEAD_TEXT=$(cat <<EOF
<---><?php\\n\
<-------->\$pageValue = "${PAGE_VALUE}";\\n\
<-------->echo(\$pageValue);\\n\
<--->?>\\n
   EOF
)

改行するときはバックスラッシュ(\)が必要

   HEAD_TEXT=$(cat <<EOF
<?php\\n #<-- スラッシュ削除
\$pageValue = "${PAGE_VALUE}";\\n #<--
echo(\$pageValue);\\n #<--
?>\\n
EOF
)

php変数用のドルマーク($)はエスケープする

phpの変数は先頭にドルマークを追加します。
そのままヒアドキュメントの中に入れてしまうと、シェル本来のドルマークと衝突してしまいますのでエラーの原因になります。

   HEAD_TEXT=$(cat <<EOF
#$pageValueのままだと、エラーになる
$pageValue = "${PAGE_VALUE}";\\n\

ヒアドキュメント内では、ドルマークを含め、シェルに関係する記号や文字はバックスラッシュ(\)でエスケープします。



以上です。

もしかしたら、静的ファイルのみで構成されるWebサイト自体あまり最近見ません。
しかし、仕様変更等で現行のファイルに対して一律の変更を加えるといのはよくあります。

この方法を使えば労力が大分減らせますので参考になさってください。   

©︎2017-2018 WebSandBag