睡人亭

秀丸エディタを使いこなす

秀丸エディタの正規表現

正規表現とは?

正規表現とは「一定のパターンで表記されている文字列を、抽象的な表記法に置き換えて表現する方法」を指します。

例えば、このような例があります。

行頭を一文字字下げしたい

よくある処理方法
各行の頭にカーソルを移動して一文字下げる(…以下全ての行に繰り返し実行)
正規表現を利用した処理方法
  1. 検索キーワードに行頭を意味する正規表現を指定
  2. 置換キーワードに「全角空白」を指定
  3. 行頭全角空白に置換→行頭に全角空白が挿入

正規表現は、上の事例のような定型的処理を大量かつ高速に実行したい場合に威力を発揮します。また、その理論上処理漏れ(上の事例の場合では字下げ忘れ)も発生しません。

他にも、以下のような場合で正規表現が有効になります。

  • (句点)の後で必ず改行したい
  • 「本文の注釈表記+番号」を一度に削除したい
  • HTML文書のマークアップ(タグ)だけを削除したい
  • 行頭の特定パターン文字(例:行頭の字下げに挿入した空白)を一括削除したい

メタ文字(メタキャラクタ)

正規表現では、文字列のパターンを表記するために、いくつかの文字に対して通常とは異なる特殊な意味を与えています。

これらの特殊文字を、正規表現ではメタ文字或いはメタキャラクタと呼んでいます。秀丸でもメタ文字利用して正規表現を表記しています。

正規表現で表記された文字列のパターンに該当する文字列を、正規表現にマッチすると呼びます。

秀丸で利用可能なメタ文字は以下の通りです。いずれも所謂半角(1byte, Latin-1相当文字)で表記する点に注意してください。

行位置を示すメタ文字

文字の数や範囲を指定するメタ文字

行位置を指定するメタ文字

^ キャレット

行頭を意味します。

行頭を表示
行頭を表示
検索する文字列
^
置換する文字列

全ての行頭にが挿入されます。

$ ドル記号

行末を意味します。

行末を表示
行末を表示
検索する文字列
$
置換する文字列

実は上の指定では、行末にが挿入されません。

行末に等の文字列を挿入したい場合は、以下のように指定してください。

検索する文字列
\n
置換する文字列
◆\n

これで、行末にが挿入されます。

\n改行を表すエスケープシーケンスです。

タグ付き正規表現を利用しても同様の結果が得られます。

検索する文字列
\n\f
置換する文字列
◆\0

文字の数や範囲を指定するメタ文字

それぞれ微妙に意味する所が異なりますので、よく覚えておいてください。

特に*+?の違いについて注意しておきましょう。

. ピリオド

改行を除く任意の一文字を表します。

二文字はピリオドを二つ、三文字は同じく三つ…と複数指定する事で、文字数を指定した検索が可能となります。

元の文字列
うり~ うりぃ~ うりぃぃ~ うりぃぃぃ~
正規表現(その1)
うり.~
マッチする文字列(その1)
うりぃ~
正規表現(その2)
うり...~
マッチする文字列(その2)
うりぃぃぃ~

* アスタリスク

直前の文字列やメタ文字の「0回以上の繰り返し」を表します。

元の文字列
うり~ うりぃ~ うりぃぃ~ うりぃぃぃ~
正規表現
うりぃ*~
マッチする文字列
うり~ うりぃ~ うりぃぃ~ うりぃぃぃ~
マッチしない文字列
なし

+ プラス記号

直前の文字列やメタ文字の「1回以上の繰り返し」を表します。

元の文字列
うり~ うりぃ~ うりぃぃ~ うりぃぃぃ~ うりぃぃぃぃ~
正規表現
うりぃ+~
マッチする文字列
うりぃ~ うりぃぃ~ うりぃぃぃ~ うりぃぃぃぃ~
マッチしない文字列
うり~

? クエスチョン

直前の文字列やメタ文字の「0回もしくは1回出現」を表します。

元の文字列
うり~ うりぃ~ うりぃぃ~ うりぃぃぃ~
正規表現
うりぃ?~
マッチする文字列
うり~ うりぃ~
マッチしない文字列
うりぃぃ~ うりぃぃぃ~

[ ] ブラケット

[ ]内の一文字または正規表現のいずれか一つを意味します。

[ ]内に、何文字あろうと、[ ]内は一文字として扱われます。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走
正規表現
[如文無]月
マッチする文字列
如月 文月 水無月 神無月

ブラケット内の文字は、メタ文字であろうと全て一文字として扱われます。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走 ?月 +月
正規表現
[如文+無?]月
マッチする文字列
如月 文月 水無月 神無月 +月 ?月

但し、ブラケット自身とエスケープコード\については、例外的にメタ文字として扱われます。

これらの文字を文字として指定するには、エスケープコードを直前に付加してください。

左ブラケット
\[
右ブラケット
\]
エスケープコード
\\

ブラケット内でのみ使用可能な特殊なメタ文字

ブラケット内で指定された時だけ意味を持つメタ文字があります。

- マイナス

範囲を指定します。文字の配列順は、文字集合に(JIS X 0208)規定されます。

全ての半角数字
[0-9]
二桁の数値00-99
[0-9][0-9]
半角英大文字
[A-Z]
半角英小文字
[a-z]
全ての全角記号
[、-◯]
全てのひらがな
[ぁ-ん]
全てのカタカナ
[ァ-ヶ]
第一水準の漢字
[亜-腕]
第二水準の漢字
[弌-熙]
※漢数字や「あ行(あいうえおだけ)の平仮名」等は、文字コード上ではバラバラに配置されていますので範囲指摘出来ません。一文字ずつ入力しましょう。
一~京までの漢数字
[一二三四五六七八九十百千万億兆京]
あ行のひらがな
[あいうえお]

^ キャレット

ブラケット内の文字列以外を意味します。

行頭を表すキャレットと同じ文字ですが、ブラケット内では意味が異なります。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走
正規表現
[^如文無]月
マッチする文字列
睦月 卯月 皐月 葉月 長月 霜月

「否定」のキャレットは、必ず左ブラケットの直後に入れてください。

途中に入れても、単にキャレットとしてしか検索されません。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走 ^月
正規表現
[如文^無]月
マッチする文字列
如月 文月 ^月 水無月 神無月

( ) パーレン

文字列を指定する正規表現です。

下で説明している|(パイプ)と組み合わせて使用します。

| (パイプ)

この文字列この文字列のどちらともマッチするという指定を行いたい場合に利用します。

ブラケットが一文字単位なのに対し、パーレンとパイプとの組み合わせでは複数文字列の指定が可能です。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走
正規表現
睦月|弥生|皐月|文月
マッチする文字列
睦月 弥生 皐月 文月

パーレンと組み合わせる事も可能です。

元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走
正規表現
(如|卯|葉|神無)月
マッチする文字列
如月 卯月 葉月 神無月
ブラケットをパーレンとパイプとの組み合わせ中に入れることも可能です。
上の例を、ブラケットとパーレン+パイプで表記してみました。
元の文字列
睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走
正規表現
([如卯葉]|神無)月
マッチする文字列
如月 卯月 葉月 神無月

注意事項―最長一致の原則―

秀丸の正規表現は最長一致という原則に従っています。

「最長一致」とは正規表現にマッチする最も長いパターンの事です。

正規表現では、メタ文字にマッチするパターンを、最長一致の原則に基づいて検索します。

従って、一行に正規表現にマッチするパターンが複数存在したとしても、場合によってはまとめて一個のパターンと誤認してしまう場合があります。

最長一致の例

例えば、以下のような文字列があったとします。

生憎<あいにくと読む>今日は雨です<困った>。 しかし<今日は>出かける<どこへ?>必要があります。

この文章の<>内の文字列をまとめて削除したい場合、以下のような正規表現が思い浮かぶかと思います。

[<>で囲まれた一文字以上の文字列]→<.+>

この正規表現を検索キーワードに指定して置換を実行してみましょう。

以下のような指定になるかと思います。

<.+>を削除
<.+>を削除

ところが、上の指定で置換を実行すると、以下のような結果になってしまいます。

生憎。 しかし必要があります。

これは、最長一致の原則に従って、検索キーワードに指定した正規表現にマッチする最も長いパターンを検索したためです。

ここでは、「両端に<>があって、中が一文字以上(当然<>も含めます)ある文字列」になりますので、以下の色つきの部分がマッチしてしまうのです。

生憎<あいにくと読む>今日は雨です<困った>。 しかし<今日は>出かける<どこへ?>必要があります。

これを回避するには、ちょっとした工夫が必要です。

「<>内の文字列を必ず検索したい」場合は、この単位を確実に指定する正規表現をすればよいわけです。

ここでは、<[^>]+>がそれに当たります。

この正規表現は、<>の中に一文字以上の文字列。但し>は除く。という意味になります。

で始まるを除く一文字以上で、しかもで終わりますので、確実に<>内の文字列だけにマッチします。