GNU Emacsにはバッファから指定したテキストを探す方法が2つあります。 文字列そのものを正確に探索するのと正規表現の探索です。 正規表現の探索のあとでは、 正規表現全体やそのさまざまな部分に一致したテキストを表す マッチデータ(match data)を調べることができます。
`skip-chars...'などの関数もある種の探索を行います。 See section 文字群の飛び越し。
これらは、バッファ内のテキストを探索するための基本関数です。
これらはプログラムで使うことを意図していますが、
対話的に呼び出すこともできます。
その場合、探索文字列を問い合わせてきますが、
limitとnoerrorはnil
に、repeatは1に設定されます。
これらの探索関数は、バッファがマルチバイトであると 探索文字列をマルチバイトに変換します。 バッファがユニバイトであると探索文字列をユニバイトに変換します。 See section テキスト表現。
つぎの例では、ポイントは始めは行頭にある。
そして(search-forward "fox")
は`fox'の最後の文字のうしろに
ポイントを移動する。
---------- Buffer: foo ---------- -!-The quick brown fox jumped over the lazy dog. ---------- Buffer: foo ---------- (search-forward "fox") => 20 ---------- Buffer: foo ---------- The quick brown fox-!- jumped over the lazy dog. ---------- Buffer: foo ----------
引数limitは探索の上限を指定する。
(カレントバッファ内の位置であること。)
その位置を越える箇所での一致は受け入れない。
limitを省略したりnil
であると、
デフォルトは、バッファの参照可能部分の末尾である。
探索に失敗した場合の動作は、noerrorの値に依存する。
noerrorがnil
であると、
エラーsearch-failed
を通知する。
noerrorがt
であると、
search-forward
はnil
を返しなにもしない。
noerrorがnil
でもt
でもないと、
search-forward
はポイントを上限位置へ移動してnil
を返す。
(この場合にもポイントの新たな値を返すほうが一貫性があるが、
値nil
に依存しているプログラムがある。)
repeatを指定してあると(正の数であること)、 その回数だけ探索を繰り返す(一致箇所の末尾を新たな探索の開始位置とする)。 連続してこれらの探索に成功すると関数は成功し、 ポイントを移動してその新たな値を返す。 さもなければ探索は失敗である。
search-forward
と同様であるが、後方へ向けて探索し
一致箇所の先頭にポイントを置く点が異なる。
単語の一致では、stringを単語の列とみなし、 それらを区切る句読点は無視する。 バッファ内の同じ単語の列を探す。 バッファ内の各単語は別々になっている必要があるが (単語`ball'を探索すると単語`balls'には一致しない)、 句読点や空白の詳細は無視される (`ball boy'を探索すると`ball. Boy!'に一致する)。
つぎの例では、ポイントは始めはバッファの先頭にある。 探索するとポイントは`y'と`!'のあいだに移動する。
---------- Buffer: foo ---------- -!-He said "Please! Find the ball boy!" ---------- Buffer: foo ---------- (word-search-forward "Please find the ball, boy.") => 35 ---------- Buffer: foo ---------- He said "Please! Find the ball boy-!-!" ---------- Buffer: foo ----------
limitがnil
以外(カレントバッファ内の位置)であると、
それは探索の上限を指定する。
みつかった一致箇所はその位置を越えてはならない。
noerrorがnil
であると、
探索に失敗するとエラーword-search-failed
を通知する。
noerrorがt
であると、
エラーを通知するかわりにnil
を返す。
noerrorがnil
でもt
でもないと、
ポイントをlimit(あるいはバッファの末尾)へ移動してnil
を返す。
repeatがnil
以外であると、
その回数だけ探索を繰り返す。
ポイントは最後の一致箇所の末尾へ置かれる。
word-search-forward
と同様であるが、
後方へ向けて探索し一致箇所の先頭にポイントを置く点が異なる。
正規表現(regular expression、略してregexp)は、 文字列の(無限の可能性もある)集合を表すパターンです。 正規表現への一致を探すことは、非常に強力な操作です。 本節では、正規表現の書き方を説明します。 続く節では、それらを探索する方法を説明します。
正規表現では、数個の文字が特別な構成であり、残りは普通です。 普通の文字は、その文字だけに一致する単純な正規表現です。 特別な文字は、`.'、`*'、`+'、 `?'、`['、`]'、`^'、`$'、`\'であり、 将来新たな文字が定義されることはありません。 正規表現に現れるこれら以外の文字は、 まえに`\'がない限り普通の文字です。
たとえば、`f'は特別な文字ではないので普通の文字です。 ですから、`f'は文字列`f'だけに一致する正規表現です。 (これは文字列`ff'には一致しない。) 同様に、`o'は`o'だけに一致する正規表現です。
任意の2つの正規表現aとbを連結できます。 その結果は、aが文字列の始めの部分に一致し、かつ、 bがその文字列の残りに一致するときにその文字列に一致する 正規表現になります。
簡単な例として、正規表現 `f'と`o'を連結して 正規表現`fo'を得られます。 これは文字列`fo'だけに一致します。 これは明らかですね。 より強力なことをするには、特別な文字の1つを使う必要があります。 それらの一覧を以下に示します。
grep
のようなプログラムでの正規表現の扱い方と対照的である。
"\\\\"
である。
注意:
従来との互換性のために、
特別な文字がそれらの特別な意味をなしえない文脈で使われた場合には、
普通の文字として扱われる。
たとえば、`*foo'では、`*'の対象となる正規表現が直前にないため、
`*'は普通の文字として扱われる。
このようなふるまいに依存することはよいことではない。
特別な文字は書く位置に関係なくクォートするべきである。
多くの場合、任意の文字を伴う`\'はその文字だけに一致します。 しかし、いくつか例外があって、 `\'で始まる2文字列が特別な意味を持つ場合があります。 (2文字目にくる文字は、 単独で使った場合にはつねに普通の文字として扱われる。) 以下に`\'の構成を示します。
つぎの正規表現は空の文字列に一致します。 つまりこれらは文字を使用しませんが、 これらが一致するかどうか文脈に依存します。
任意の文字列が正しい正規表現ではありません。
たとえば、(`[]]'のような少数の例外を除けば)
角括弧が対応していない文字列は正しくありませんし、
1つの`\'で終る文字列も正しくありません。
不正な正規表現を探索関数に渡すと、
エラーinvalid-regexp
が通知されます。
(regexp-quote "^The cat$") => "\\^The cat\\$"
regexp-quote
の用途の1つは、
正規表現で記述された文脈に正確に一致する文字列を組み合わせることである。
たとえば、つぎは、白文字で囲まれたstringの値で表される文字列を探索する。
(re-search-forward (concat "\\s-" (regexp-quote string) "\\s-"))
省略可能な引数parenがnil
以外であると、
返される正規表現はつねに少なくとも1つの括弧によるグループ構文で囲まれる。
つぎのregexp-opt
の簡略版定義は、
実際の値に等価な(ただしそれほど効率よくない)正規表現を生成する。
(defun regexp-opt (strings paren) (let ((open-paren (if paren "\\(" "")) (close-paren (if paren "\\)" ""))) (concat open-paren (mapconcat 'regexp-quote strings "\\|") close-paren)))
ここでは、任意個数の白文字を伴った文末を認識するために
Emacsで使われている複雑な正規表現について述べます。
それは変数sentence-end
の値です。
まず、タブ文字と空白を区別するためにLisp構文の文字列として 正規表現を示します。 文字列定数はダブルクォートで始まり終ります。 `\"'は文字列の一部としてのダブルクォート、 `\\'は文字列の一部としてのバックスラッシュ、 `\t'はタブ、`\n'は改行を表します。
"[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*"
対照的に、変数sentence-end
を評価するとつぎのように
なっているはずです。
sentence-end => "[.?!][]\"')}]*\\($\\| $\\| \\| \\)[ ]*"
この出力では、タブと改行はそれ自身として現れています。
この正規表現には、連続してつぎのような4つの部分が含まれています。
[.?!]
[]\"')}]*
\"
は、文字列内のダブルクォートを表すLisp構文である。
最後の`*'は、直前の正規表現(この場合は文字選択)を
0回以上繰り返すことを表す。
\\($\\| $\\|\t\\| \\)
[ \t\n]*
GNU Emacsでは、正規表現に一致するつぎの部分を
インクリメンタルにもそうでなくも探せます。
インクリメンタルサーチコマンドについては、
section `正規表現探索' in GNU Emacs マニュアルを
参照してください。
ここでは、プログラムで有用な探索関数のみについて述べます。
基本的なものはre-search-forward
です。
これらの探索関数は、バッファがマルチバイトであれば 正規表現をマルチバイトに変換します。 バッファがユニバイトであれば、正規表現をユニバイトに変換します。 See section テキスト表現。
limitがnil
以外(カレントバッファ内の位置であること)であると、
探索の上限を表す。
その位置を越える箇所での一致は受け入れない。
repeatを指定してあると(正の数であること)、 その回数だけ探索を繰り返す(一致箇所の末尾を新たな探索の開始位置とする)。 連続してこれらの探索に成功すると関数は成功し、 ポイントを移動してその新たな値を返す。 さもなければ探索は失敗である。
関数が失敗した場合の動作は、noerrorの値に依存する。
noerrorがnil
であると、
エラーsearch-failed
を通知する。
noerrorがt
であると、
re-search-forward
はなにもせずにnil
を返す。
noerrorがnil
でもt
でもないと、
re-search-forward
はポイントをlimit(あるいはバッファの末尾)へ
移動してnil
を返す。
つぎの例では、ポイントは始めは`T'のまえにある。 探索を呼び出すと、ポイントは当該行の末尾 (`hat'の`t'と改行のあいだ)へ移動する。
---------- Buffer: foo ---------- I read "-!-The cat in the hat comes back" twice. ---------- Buffer: foo ---------- (re-search-forward "[a-z]+" nil t 5) => 27 ---------- Buffer: foo ---------- I read "The cat in the hat-!- comes back" twice. ---------- Buffer: foo ----------
この関数はre-search-forward
に類似したものであるが、
単純な鏡像ではない。
re-search-forward
は、一致箇所の先頭が
開始位置に可能な限り近い一致箇所を探す。
re-search-backward
が完全な鏡像であれば、
一致箇所の末尾が可能な限り近い一致箇所を探す。
しかし、実際には、一致箇所の先頭が可能な限り近い一致箇所を探す。
これは、正規表現との一致をとる処理は、
指定開始位置において先頭から末尾へ向けてつねに行われるからである。
re-search-forward
の完全な鏡像には、
正規表現の一致を末尾から先頭へ向けて行う特別な機能が必要である。
それを実装する手間をかけるほどの価値はない。
nil
を返す。
startがnil
以外であると、
stringの指定した添字から探索を始める。
たとえばつぎのとおりである。
(string-match "quick" "The quick brown fox jumped quickly.") => 4 (string-match "quick" "The quick brown fox jumped quickly." 8) => 27
文字列の最初の文字の添字は0であり、 2番目の文字の添字は1であるといった具合になる。
この関数から戻ったあとでは、
一致箇所を越えた最初の文字の添字は(match-end 0)
で得られる。
see section マッチデータ。
(string-match "quick" "The quick brown fox jumped quickly." 8) => 27 (match-end 0) => 32
t
であり、さもなければnil
である。
この関数はポイントを移動しないが、マッチデータを更新する。
match-beginning
やmatch-end
を使ってマッチデータを参照できる。
つぎの例では、ポイントは`T'の直前にある。
ポイントがこれ以外の場所にあると結果はnil
になる。
---------- Buffer: foo ---------- I read "-!-The cat in the hat comes back" twice. ---------- Buffer: foo ---------- (looking-at "The cat in the hat$") => t
普通の正規表現関数は、`\|'や反復構文を扱うために必要なときには バックトラックしますが、これを行い続けるのは なんらかの一致をみつけるまでです。 みつけてしまえば、それらは成功してみつけた最初の一致を報告します。
本節では、正規表現の一致に関するPOSIX規格で規定された 完全なバックトラックを行う代替の探索関数について述べます。 それらはすべての可能性を試し尽くしすべての一致箇所を探し終える までバックトラックを継続してます。 そのため、POSIXで要求されるとおりの最長の一致を報告できるのです。 これは動作がとても遅いですから、最長一致が本当に必要な場合に限って これらの関数を使ってください。
re-search-forward
と同様であるが、
正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。
re-search-backward
と同様であるが、
正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。
looking-at
と同様であるが、
正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。
string-match
と同様であるが、
正規表現の一致に関するPOSIX規格で規定された完全なバックトラックを行う。
query-replace
と関連するコマンドの中身である。
from-stringの出現を探しだし、それらの一部やすべてを置き換える。
query-flagがnil
であると、すべての出現を置換する。
さもなければ、1つ1つユーザーにどうするかを問い合わせる。
regexp-flagがnil
以外であると、
from-stringを正規表現として扱う。
さもなければ、その字面とおりに一致する。
delimited-flagがnil
以外であると、
単語区切りで囲まれたもののみを対象にする。
引数replacementsは、出現を置き換えるものを指定する。 それが文字列であれば、その文字列を使う。 文字列のリストでもよく、要素を巡回して使う。
repeat-countがnil
以外であれば、整数であること。
これは、replacementsのリスト内の各文字列を
つぎに進めるまえに何回使用するかを指定する。
通常、キーマップquery-replace-map
で、
可能なユーザーの応答を定義する。
引数mapがnil
以外であれば、
query-replace-map
のかわりに使うキーマップである。
y-or-n-p
やmap-y-or-n-p
に加えて、
query-replace
や関連する関数に対する
正しいユーザー応答を定義する特別なキーマップを保持する。
2つの意味で普通のものではない。
read-key-sequence
を使わずに、
『自前』でイベントを読み取り探索するからである。
query-replace-map
向けの意味のある『バインディング』をつぎに示します。
query-replace
と関連するものだけに意味のあるものもあります。
act
skip
exit
act-and-exit
act-and-show
automatic
backup
edit
delete-and-edit
recenter
quit
y-or-n-p
と関連する関数でのみ、この応答を用いる。
help
Emacsは、正規表現の探索中に捜し出したテキスト断片の開始/終了位置を 記録しています。 つまり、たとえば、rmailメッセージ内で日付のような複雑なパターンを 探索してから、パターンの制御をもとに一致した一部分を取り出せるのです。
マッチデータは、通常、もっとも最近に行った探索のみを記述するので、 あとで使用したい探索とそのマッチデータを使うあいだに、 不注意に別の探索を行わないように注意してください。 あいだで探索を行う必要がある場合には、その周りで マッチデータを保存/復元してそれらが上書きされないようにします。
この関数は、最後の探索で一致したテキストをreplacementで置換します。
バッファで最後に探索を行った場合には、
stringにnil
を指定すること。
そうすると、replace-match
はバッファを編集することで置換を行い、
置換したテキストの末尾にポイントを置きt
を返す。
文字列で探索した場合には、stringに同じ文字列を渡すこと。
そうすると、replace-match
は新たな文字列を構築することで
置換を行い、新たな文字列を返す。
fixedcaseがnil
以外であると、
置換テキストの大文字小文字は変更しない。
さもなければ、置換テキストの大文字小文字は、
対象テキストの大文字小文字に応じて変換される。
元テキストがすべて大文字であると、置換テキストも大文字に変換される。
元テキストの最初の単語が大文字で始まっていると、
置換テキストの最初の単語も大文字で始める。
元テキストが1単語のみであり、しかも、その単語が大文字1文字であると、
replace-match
はすべてが大文字ではなく大文字で始まるとみなす。
case-replace
がnil
であると、
fixed-caseの値に関わらず、大文字小文字変換を行わない。
see section 探索と大文字小文字。
literalがnil
以外であると、
必要に応じて大文字小文字変換は行うものの
replacementをそのまま挿入する。
それがnil
(デフォルト)であると、
文字`\'を特別に扱う。
replacementに`\'が現れるときには、
つぎの列のいずれかであること。
subexpがnil
以外であると、
一致箇所全体ではなく正規表現のsubexp番目の部分式に
一致した箇所のみを置換することを指示する。
たとえば、`foo \(ba*r\)'に一致させたあとで、
subexpに1を指定してreplace-match
を呼び出すと、
`\(ba*r\)'に一致したテキストのみを置換することを意味する。
本節では、最後の探索や一致操作において なにに一致したのかを調べるためのマッチデータの使い方を説明します。
一致したテキスト全体や正規表現の括弧で括った特定の部分式に一致した テキストを調べることができます。 以下の関数の引数countでどれかを指定します。 countがゼロであれば、一致全体を調べることになります。 countが正であれば、望みの部分式を指定します。
正規表現の部分式は、エスケープした括弧`\(...\)'でグループ化した 式であることに注意してください。 count番目の部分式は、正規表現全体の先頭から `\('の出現を数えてみつけます。 最初の部分式は1、つぎは2、といった具合です。 部分式は正規表現だけにあります。 単純な文字列探索のあとでは、利用可能な情報は一致全体に関するものだけです。
探索に失敗すると、マッチデータを変更することもしないこともあります。 過去には探索に失敗しても変更しなかったのですが、 将来そうなります。
nil
である。
最後の探索や一致操作をstring-match
で文字列に対して行った場合には、
引数in-stringとして同じ文字列を渡すこと。
バッファの探索や一致のあとでは、in-stringを省略するか
nil
を渡すこと。
ただし、match-string
を呼び出すときのカレントバッファが
探索を行ったときのバッファであること。
match-string
と同様であるが、
結果にはテキスト属性を含まない。
countがゼロであると、値は一致全体の開始位置である。 さもなければ、countは正規表現内の部分式を指定し、 関数の値は当該部分式に一致した部分の開始位置である。
一致に利用されなかった選択肢`\|'内の部分式に対しては、
値はnil
である。
match-beginning
と同様であるが、
一致箇所の開始位置ではなく終了位置を返す点が異なる。
コメントでテキスト内の位置を示しながら マッチデータの利用例を示します。
(string-match "\\(qu\\)\\(ick\\)" "The quick fox jumped quickly.") ;0123456789 => 4 (match-string 0 "The quick fox jumped quickly.") => "quick" (match-string 1 "The quick fox jumped quickly.") => "qu" (match-string 2 "The quick fox jumped quickly.") => "ick" (match-beginning 1) ; 一致箇所`qu'の先頭は => 4 ; 添字4 (match-beginning 2) ; 一致箇所`ick'の先頭は => 6 ; 添字6 (match-end 1) ; 一致箇所`qu'の末尾は => 6 ; 添字6 (match-end 2) ; 一致箇所`ick'の末尾は => 9 ; 添字9
別の例も示します。 ポイントは始めは行頭にあります。 探索によって、ポイントは空白と単語`in'のあいだに移動します。 一致箇所全体の先頭はバッファの9番目の文字(`T')であり、 最初の部分式の一致箇所の先頭は13番目の文字(`c')です。
(list (re-search-forward "The \\(cat \\)") (match-beginning 0) (match-beginning 1)) => (9 9 13) ---------- Buffer: foo ---------- I read "The cat -!-in the hat comes back" twice. ^ ^ 9 13 ---------- Buffer: foo ----------
(この例では、返される添字はバッファ内位置であり、 バッファの最初の文字を1と数える。)
関数match-data
とset-match-data
は、
マッチデータ全体を一度に読んだり書いたりします。
(match-beginning n)
に対応し、
要素
は(match-end n)
に対応する。
バッファで行った一致ではすべての要素はマーカかnil
であり、
string-match
により文字列で行った一致では
すべての要素は整数かnil
である。
探索関数の呼び出しとその探索結果としてのマッチデータを参照するための
match-data
の呼び出しのあいだには、
別の探索があってはならない。
(match-data) => (#<marker at 9 in foo> #<marker at 17 in foo> #<marker at 13 in foo> #<marker at 17 in foo>)
match-data
の呼び出しで得たリストであること。
match-listが存在しないバッファを指していても、エラーにはならない。 無意味な情報をマッチデータに設定するが、害にはならない。
探索を行う可能性がある関数を呼び出す場合、 あとで使うためにそれ以前の探索によるマッチデータを保存したいときには、 当該関数の呼び出しの周りでマッチデータを保存し復元する必要があります。 つぎの例は、マッチデータを保存し損なった場合に生じる問題点を 示しています。
(re-search-forward "The \\(cat \\)")
=> 48
(foo) ; foo
はさらに
; 探索する
(match-end 0)
=> 61 ; 予期しない結果。48でない!
マッチデータの保存と復元はsave-match-data
で行えます。
スペシャルフォームsave-match-data
の効果をまねるために
match-data
とともにset-match-data
を使うこともできます。
つぎのようにします。
(let ((data (match-data))) (unwind-protect ... ; もとのマッチデータを変更しても大丈夫 (set-match-data data)))
プロセスフィルタ関数(see section プロセスフィルタ関数)や プロセスの番兵(see section 番兵:プロセスの状態変化の検出)を実行するときには、 Emacsは自動的にマッチデータを保存し復元します。
デフォルトでは、Emacsの探索は探索対象テキストの大文字小文字を区別しません。 `FOO'を探す指定を行うと、 `Foo'や`foo'にも一致するとみなします。 これは、正規表現にも適用されます。 したがって、`[aB]'は、`a'や`A'や`b'や`B'に一致します。
この機能を望まないときには、
変数case-fold-search
にnil
を設定します。
すると、すべての文字は大文字小文字を保ってそのとおりに一致します。
これはバッファローカルな変数ですから、
変数を変更してもカレントバッファだけに影響します。
(see section バッファローカルな変数の紹介。)
あるいは、default-case-fold-search
の値を変更します。
これは、case-fold-search
を書き変えていないバッファ向けの
デフォルト値です。
ユーザーレベルのインクリメンタルサーチ機能では、 大文字小文字の区別は異なった扱い方をします。 小英文字を与えるとその大文字にも一致しますが、 大英文字を与えると大文字のみに一致します。 しかし、これはLispコードで使用している探索関数には まったく関係ありません。
nil
であると、置換テキストをそのまま使うことを意味する。
nil
以外の値であると、置換対象のテキストに応じて
置換テキストの大文字小文字を変換することを意味する。
この変数が実際に効果を発揮するのは関数replace-match
においてである。
see section 一致したテキストの置換。
nil
であると大文字小文字を区別する。
さもなければ大文字小文字を区別しない。
case-fold-search
を書き変えていないバッファ向けの
デフォルト値である。
これは(default-value 'case-fold-search)
と同じである。
本節では、編集上の特定目的に用いられる正規表現を保持している 変数について述べます。
"^\014"
(つまり、"^^L"
すなわち"^\C-l"
)
である。
これはページ送り文字で始まる行に一致する。
つぎの2つの正規表現は、つねに行の先頭から一致が 始まると仮定してはいけません。 一致の開始位置を固定する`^'を使うべきではありません。 ほとんどの場合、段落コマンドは行の先頭でのみ一致を検査しますから、 `^'は不必要であることを意味します。 幅0以外の左端余白があると、段落コマンドは左端余白のうしろからの一致を 受け入れます。 そのような場合、`^'は誤りです。 しかし、左端余白をけっして使わないモードならば、 `^'は無害です。
paragraph-start
も変更すること。)
デフォルト値は"[ \t\f]*$"
であり、
(左端余白に続く)空白やタブやページ送りだけから成る行に一致する。
"[ \t\n\f]"
であり、
(左端余白に続く)空白やタブやページ送りだけから成る行に一致する。
"[.?!][]\"')}]*\\($\\| $\\|\t\\| \\)[ \t\n]*"
これは、ピリオド、疑問符、感嘆符のいずれかのあとに 閉じ括弧文字が続き(なくてもよい)、 タブや空白や改行が続くことを意味する。
この正規表現の詳しい説明は、section 複雑な正規表現の例を参照。
Go to the first, previous, next, last section, table of contents.