replace.py 技術ドキュメント
プログラムの動作
replace.py は、指定されたテキストファイルの内容を、設定ファイルで定義された正規表現パターンに基づいて置換するプログラムです。主に、大量のテキストデータにおける表記ゆれや特定のフレーズの一括修正、あるいは書式変換などの用途に利用できます。
主な機能:
入力ファイルの文字コード自動検出:
chardetライブラリを使用して、入力ファイルの文字コードを自動的に判定し、適切に読み込みます。柔軟な置換ルール定義:
INI形式の設定ファイル (replace.iniなど) から、正規表現パターンとその置換文字列のペアを読み込みます。ユーザー定義ルールの優先: デフォルトの置換ルールファイルとユーザー定義の置換ルールファイルの両方を指定でき、ユーザー定義ルールがデフォルトルールよりも優先されます。重複するキーはユーザー定義ルールが適用され、デフォルトルールからは除外されます。
正規表現による強力な置換: Pythonの
reモジュールを利用し、大文字小文字を区別しない、複数行対応などのフラグを設定した正規表現置換を実行します。自動的な出力ファイル名生成: 出力ファイルが指定されない場合、入力ファイル名に
-convertedを付加した名前で自動生成します。
原理
このプログラムは以下の原理に基づいて動作します。
ライブラリの事前チェック: 必要な非標準ライブラリ(
chardet)がインストールされているかを確認し、不足している場合はエラーメッセージを表示して終了します。文字コード検出:
detect_encoding関数は、入力ファイルをバイナリモード ('rb') で読み込み、chardet.detect()関数を用いてファイルの文字コードを推定します。これにより、多種多様なエンコーディングのファイルに対応できます。置換辞書のロード:
load_replace_dict関数は、指定されたINIファイルを解析し、キー=値の形式の行を置換ルールとして辞書に格納します。行頭が
#の行はコメントとして無視されます。キーは正規表現パターン、値は置換文字列です。
キーがシングルクォートまたはダブルクォートで囲まれている場合 (
'key'=valueまたは"key"=value)、クォートを削除してキーとして使用します。この解析には、3重引用符 で囲まれた正規表現リテラル
r"^(['\"].+?['\"]|[^=]+?)=(.*)$"が使用され、キーと値を正確に抽出します。
置換ルールの適用順序と優先順位:
ユーザー定義の置換ファイル (
replace_file2) とデフォルトの置換ファイル (replace_file) の両方が読み込まれます。dict2(ユーザー定義) に存在するキーはdict1(デフォルト) から除外されます。これにより、ユーザー定義のルールがデフォルトのルールよりも優先されます。置換はまず
dict2のルール群がテキスト全体に適用され、次にdict1_filteredのルール群が、dict2適用後のテキストに適用されます。各ルールは辞書からリストに変換された順序で一つずつ適用されます。
正規表現置換:
apply_replacements関数は、与えられたテキストに対し、正規表現パターンと置換文字列のペアを順次適用します。re.sub(pattern, replacement, text, flags=re.IGNORECASE | re.MULTILINE)を使用して置換を実行します。re.IGNORECASEフラグにより、大文字小文字を区別せずにパターンマッチングを行います。re.MULTILINEフラグにより、正規表現の^と$が行頭と行末にマッチするようになります。
出力: 全ての置換処理が完了した後、最終的なテキストは指定された出力ファイルにUTF-8エンコーディングで書き込まれます。
このプログラムでは、特定の数式や物理式は直接使用されていません。アルゴリズムは主にテキスト処理と正規表現に基づいています。
必要な非標準ライブラリとインストール方法
このプログラムは、文字コードの自動検出のために以下の非標準ライブラリを必要とします。
chardet: ファイルのエンコーディングを検出するために使用されます。
インストール方法:
コマンドプロンプトやターミナルで以下の pip コマンドを実行してインストールできます。
pip install chardet
必要な入力ファイル
1. 入力テキストファイル
置換処理の対象となるテキストファイルです。
パス: コマンドライン引数
--input_fileまたは-iで指定します。指定しない場合、デフォルトでinput.mdが使用されます。形式: 任意のテキスト形式(例:
.md,.txt,.htmlなど)。プログラムが自動で文字コードを検出しようと試みます。
2. 置換ルールファイル (INI形式)
置換パターンと置換文字列を定義するファイルです。
パス:
デフォルトの置換ルールファイル: コマンドライン引数
--replace_fileまたは-rで指定します。指定しない場合、デフォルトでreplace.iniが使用されます。ユーザー定義の置換ルールファイル: コマンドライン引数
--replace_file2または-sで指定します。指定しない場合、デフォルトで空文字列が使用され、ファイルは読み込まれません。
形式: INIファイル形式に似たシンプルなキーバリューペアのリストです。
各行は
正規表現パターン=置換文字列の形式で記述します。行頭が
#の行はコメントとして無視されます。正規表現パターン(キー)は、シングルクォート
'またはダブルクォート"で囲むことができます。この場合、クォートはキーとして扱われず、パターンの一部と見なされます。置換文字列(値)は、前後の空白を含めてそのまま扱われます。
replace.ini の例:
# This is a comment line.
"古いテキスト"=新しいテキスト
パターンA=置換文字列A
'Pattern B'=Replacement B With Spaces
[0-9]+=[NUMBER]
生成される出力ファイル
置換処理が適用された結果のテキストが保存されるファイルです。
ファイル名: コマンドライン引数
--output_fileまたは-oで指定します。指定がない場合、入力ファイル名に
-convertedを付加した名前が自動で生成されます。例:
input.md->input-converted.md例:
document.txt->document-converted.txt
内容: 入力テキストに全ての置換ルールが適用された後の最終的なテキスト。
文字コード:
UTF-8で書き出されます。
コマンドラインでの使用例 (Usage)
replace.py は以下の形式でコマンドラインから実行します。
python replace.py [-i INPUT_FILE] [-o OUTPUT_FILE] [-r REPLACE_FILE] [-s REPLACE_FILE2]
引数:
-i INPUT_FILE,--input_file INPUT_FILE: 入力テキストファイルのパス。デフォルトはinput.md。-o OUTPUT_FILE,--output_file OUTPUT_FILE: 出力ファイルのパス。指定がない場合、入力ファイル名から自動生成されます。-r REPLACE_FILE,--replace_file REPLACE_FILE: デフォルトの置換ルールファイル (.ini) のパス。デフォルトはreplace.ini。-s REPLACE_FILE2,--replace_file2 REPLACE_FILE2: ユーザー定義の置換ルールファイル (.ini) のパス。このファイルに定義されたルールは、デフォルトファイルと重複する場合に優先されます。デフォルトは空文字列 (指定なし)。
コマンドラインでの具体的な使用例
以下のファイルが存在すると仮定します。
input.txt の内容:
Hello World! This is a test.
Test for REPLACE.
replace.ini の内容 (デフォルトルール):
World=Python
Test=Example
user_replace.ini の内容 (ユーザー定義ルール、Test が replace.ini と重複):
Hello=Hi
Test=UserTest
実行コマンド
input.txt を読み込み、replace.ini と user_replace.ini のルールを適用して output.txt に出力します。
python replace.py -i input.txt -o output.txt -r replace.ini -s user_replace.ini
実行結果の説明
上記のコマンドを実行すると、以下のようなプロセスを経て output.txt が生成されます。
入力ファイル読み込み:
input.txtが読み込まれます。置換辞書ロード:
user_replace.iniから{ 'Hello': 'Hi', 'Test': 'UserTest' }が読み込まれ、ユーザー定義ルール (dict2) となります。replace.iniから{ 'World': 'Python', 'Test': 'Example' }が読み込まれ、デフォルトルール (dict1) となります。
ルール優先順位の適用:
dict2に'Test'が存在するため、dict1から'Test'ルールが除外されます。結果として、適用されるデフォルトルールは
{ 'World': 'Python' }(dict1_filtered) となります。
置換処理:
まず、ユーザー定義ルール (
dict2) が適用されます。Hello→HiTest→UserTestこの段階でテキストは
Hi World! This is a UserTest.\nUserTest for REPLACE.となります。
次に、フィルターされたデフォルトルール (
dict1_filtered) が適用されます。World→Pythonこの段階でテキストは
Hi Python! This is a UserTest.\nUserTest for REPLACE.となります。
出力: 最終的なテキストが
output.txtに書き出されます。
output.txt の内容:
Hi Python! This is a UserTest.
UserTest for REPLACE.