bulk replace / traps
一括置換の罠6つ:実際に壊した例と、上げる前の検算
結論です。一括置換は「当たった件数」でなく「壊れていないこと」を検査します。変えたかった箇所だけを見て終わりにすると、壊れたのは変えるつもりのなかった側だった、という事故になります。このページは、2026年8月から9月に複数のセッションが踏んだ6つの罠を、再現できる形で並べた記録です。短い語が長い語を食う、新しい文が古い文を含んで入れ子になる、条件が文を切って約束だけが残る、正規表現が配列の括弧を食う、関数形式の置換が後方参照を落とす、空白を捕まえた値が判定をすり抜ける、の6つです。
このサイトはAnthropicの公式サイトではありません。Claude Codeの機能・料金・提供範囲は変わる可能性があるため、重要な判断の前には公式のドキュメントと自分のアカウント設定を確認してください。
先に結論:置換の前後で測る4つ
- 置換の前に、対象の件数を数える。想定と合わなければ、先に当たった罠を疑います。2026年9月23日の例では、下見で49件のはずが0件でした。
- 置換の後に、「壊れていないこと」を測る。タグの開閉数、括弧の釣り合い、
$1のような文字がそのまま残っていないか。 - わざと違反を入れて、検査が鳴るか確かめる。鳴らない検査は「合格」と見分けがつきません。
- 書き換える生成元は、先に控える。出力の控えだけでは足りません。
罠1と2:短い語が長い語を食う、新しい文が古い文を含む
2026年9月23日、受付条件の約束を全サイトで直したとき、複数のセッションが同じ罠を踏みました。素の split().join() を直接使わず、専用の置換道具を通す決まりになりました。
| 罠 | 起きること | 対策 |
|---|---|---|
| 短い文字列を先に当てる | 「年齢の上限はありません。」を先に当てると、それを含む長い文(構造化データ側)が壊れ、長い方がもう当たらない。下見で49件のはずが0件 | 長い順に当てる。長さの降順に並べ替えてから処理する |
| 新しい文が古い文を含む | 置換後の文が置換前の文を含むと、次の周でもう一度置換されて入れ子になる。7件のはずが70件 | いったん本文に出ない目印へ逃がし、全部終わってから戻す |
罠3:条件を切る置換は、約束だけを残す
「年齢の上限はありません。」で文を切り、2文目に「40歳以上の方は写真が必要です。」と続けると、1文目だけが無条件の約束として引用されます。構造化データの回答が途中までで検索結果に出ることもあります。正しい形は「年齢の上限はありませんが、40歳以上の方は写真が必要です。」のように、条件を1文の中で完結させることです。置換の前に、新しい文に条件の無い言い切りが残っていないかを、機械で検算します。
罠4:別の書き方に当たらない
2026年8月28日、「札や行のどこを押しても店へ行く」を入れる直しで、一つの形のセルは3か所ヒットし、3つとも直しました。しかし同じ意味を別の変数名で書いた形は、1か所も当たりませんでした。コース時間別の表だけが取り残され、3店が押せないまま本番に出ました。ソースだけを見ていれば「全部直した」で終わっていました。
対策は、生成物の側から数え直すことです。「本文に出ている店名」と「リンクになっている店名」の差を取り、その検査をビルドに常設しました。足した検査は、1か所リンクを外して「押せない店名が3件ある」と出ることを見てから戻しました。生成するコードでは正規表現を使わず、文字列の分割と位置検索で書く、という決まりにもなりました。生成ファイルに書いたバックスラッシュが食われる事故を3回踏んだためです。
罠5:リンク記法を外す正規表現が配列の括弧を食う(2026年9月26日)
本文のリンク記法を外すのに、角括弧の中を「閉じ括弧以外」と指定した正規表現を使いました。この指定は開き括弧も含みます。そのため、手前にある配列の開き括弧から一致が始まり、配列の開き括弧と本文の一部が消えました。結果は、10箇所の行から配列の開きが消え、閉じない角括弧が残った文が11本、構文エラーになったファイルが3つでした。遅延一致にしても、開始位置は最も左が優先されるので防げません。
対策は、除外クラスに開き括弧も入れること([^[\]] の形)と、直した後に構文チェックと行単位の括弧の釣り合いを測ることです。壊れた場合に失われるのは、配列の開き括弧とリンクの閉じ部分だけなので、入れ直せば戻せます。
罠6と7:関数形式の置換、空白を捕まえた値
2026年8月23日、text.replace(re, () => "$1" + 中身 + "$2") と書き、関数形式では $1 が展開されず、文字列の「$1」がそのまま書かれました。本番の4ファイルで、タグが消えて「$1」「$2」の文字に置き換わりました。ツールは「OK」と出し、変えた箇所のタイトルとリードは正しかったので、変えていない側の壊れに気づくのが遅れました。後方参照を使うなら文字列を渡すか、関数の引数で受け取って自分でつなぎます。書き換えたファイルは、書き込みの前に「壊れていないこと」を検査します。
シェル経由の置換にも罠があります。2026年8月27日、Bash から流した置換でバックスラッシュが落ち、検査用の道具が構文エラーになりました。正規表現を書くときは、ヒアストリングを経由せず、ファイルに直接書きます。また改行がCRLFのファイルでは、LF決め打ちの正規表現が外れます。
もう1つは、空白を捕まえて判定をすり抜けた例です。2026年8月28日、業種を読む正規表現が18,609行すべてで失敗していました。取り出した値が改行だけで、整形すると空文字になります。空文字は偽として扱われ、「読めなかった」に分類されたため、絞り込みが丸ごと素通りして、例外も出ませんでした。結果として、30店を全部同じ業種として記録していました。
件数が合わないときの読み方
下見の件数が想定とずれたときは、少ない場合と多い場合で原因が違います。想定より少ないなら、短い語が長い語を食った(罠1)か、別の書き方がある(罠4)か、改行の種類が違う、のどれかです。想定より多いなら、新しい文が古い文を含んでいる(罠2)疑いが濃いです。ずれを「だいたい合っている」で流さず、原因が分かるまで上げないのが、いちばん安い保険です。
よくある質問
置換の道具を自作すべきですか?
置換の順序(長い順)、目印への退避、条件の検算の3つを備えた共通の道具を1つ決め、素の置換を直接使わないのが現実的です。
壊れたかどうかを機械で測るには?
タグの開閉数と、括弧の釣り合い、$1 のような置換記号が残っていないか、構文チェック(node --check や php -l)の4つを、上げる前に流します。
置換の前にやるべきことは?
一括編集の前の退避を取り、変わったファイルだけを上げます。