複数ファイルをsedで書き換える

目次

公開日 2023-04-24 更新日 -

ファイルの変更は置換と行挿入

ページエクスペリエンスが良好なURLはありませんと言われたよの方針にそって、役に立たないお話(ここです)の各ページに表示されるページ内目次の表示を見直しました。

ページ内目次はolとして作成されて、起動時の引数に文字列を指定してそれと一致したid属性を持つ要素の後ろに挿入できるように設計されています。そして、ほとんどのページではh1タグに id="top" とあり、引数が 'top' なのでh1の後ろに挿入されています。ですから、detailsタグに別のidをつけてh1のすぐ後ろに配置し、引数をそれに変更すればそれだけで完了です。

前後のh2へのジャンプをするリンクの挿入もなくすことにしましたが、これは h2indexandback.js ひとつのファイルの当該箇所の削除だけで済みます。

[1]: mia???.htmlの withpfback('top');withpfback('h2menu'); に変更する。

[2]: mia???.htmlの <h1>行の次に<details>\n<summary id="h2menu">目次</summary>\n</details>を追加する。

つまり、

<h1 id="top">awkでファイル名とタイムスタンプを変更するスクリプトを作る</h1>
<details>
<summary id="h2menu">目次</summary>
</details>

とするということです。

sed概要

テキストファイルを行ごとに読んで変更を加える。

sed --help で使用法とオプションを確認

使用法: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

最初の文字列をscript(=文字列操作指示)とし、それ以降は入力ファイル名とするということ。これを省いて標準入力やパイプを使用できる。

オプション

-e script : -eはexpressionで正規表現ではない
-f script-file : scriptをfileから読み込む
-i[SUFFIX] : in-place 直接入力ファイルを書き換える(SUFFIX文字列があればもとのファイルが、それをつけたファイルに残る)
-E, -r : regexp-extended 正規表現としてscriptを解釈する

[1]sedによる文字列置換

scriptに "s/変更前文字列/変更後文字列/" を使う。1行にwithpfback('top');は一つしかないので、最後にgはつけなくてよい。

sed -e "s/withpfback('top')/withpfback('h2menu')/" -i mia*.html

ファイル名がmiaで始まり.htmlで終わるファイルについて、すべての行を調べてwithpfback('top')が含まれていたら、withpfback('h2menu')に置換する。

-iがあるので、直接編集する。前もってファイルのバックアップをとっているので、ここではSUFFIXを指定していない。

必要ならば次のようなチェックを

grep withpfback mia*.html
diff mia001.html ../miscback/mia001.html 

このスクリプトは重複して通しても問題ない。

[2]sedによる行の挿入

scriptに "/検索文字列/a続く行に挿入される文字列" を使う。aはappendで、i(insert)なら前の行に挿入される

残念ながら、sed --help や man sed では、十分な情報が得られない。

sed  '/<\/h1>/a <details>\n<summary id="h2menu">目次</summary>\n</details>'  -i mia00?.html

ファイル名がmia00で始まり、次に任意の一文字があり、.htmlで終わるファイルについて、すべての行を調べて</h1>が含まれていたら、次の行に<details>以下を挿入する。

挿入文字列に\nを入れているので、3行の挿入になるが、これをなくして1行の挿入にしてもhtmlの観点からは違いはない。

終了タグ</h1>を使っているのは開始タグにidが入っていたりするから。mia*.htmlにはh1タグがページ内に2つあることはないので、これでいける。

このスクリプトは同じファイルに重複して実行するとどんどん付け加わるので、まずい。mia00?.html にして小分けにしているのは、確認後にmia01?.htmlなどと次に進めていくという手順を踏んだことによる。