1.5. 検索・置換
1.5.4. ワイルドカード検索・置換
75 (4) 最右最短一致(rightmost-shortest match) 検索式:M[^M]*?Z
xxMxxMxxx<*MxxZ*>xxxZxxxxxxxZxx
(1)では、検索式の「.*」が任意の文字がゼロ個以上あることを示し、それが最 初に(最左で)一致する部分から最大限まで拡張して一致しています。そこで、(2) では「?」をつけて最短一致させると、最初に一致する(最左の)部分から最短で 一致します。次に、(3)では「[^M]*」により M 以外の文字の連続を指定すると、
途中で M が現れることを防ぎ、検索は最右から始まります。ここで「[^M]*」は 最長一致するので、さらに(4)で「?」をつけて真の最短一致をさせます。一致の開 始点が2文字以上のときは次のように「(...)」でグループ化します。
検索式:MN[^(MN)]*?Z
xxMNxxMNxxx<*MNxxZ*>xxxZxxxxxxxZxx
このように厳密に最短一致で検索するときは細かな指定が必要ですが、実際に は(2)の最左最短一致で十分です。TEXTOSではこの場合 M**Z という検索式を使 います。
76
などを検索します。全角文字と半角文字の間は単語の境界にはなりません。
> 単語の末尾に境界として一致します。たとえば、ed>で、called, surprised, visited などを検索します。(全角文字と半角文字の間は単語の境界にはなりません。)
文字セット
[...] 指定した文字のいずれかに一致します。たとえば、b[ai]tでbatと bit を検索
します。
[-] 指定した範囲内の任意の 1 文字に一致します。例[n-t]ightでnight, right, sight,
tightを検索します。 範囲は昇順で指定します。×[t-n]
[!x-z] [...]内の範囲に含まれる文字を除く任意の 1 文字に一致します。例 t[!a-m]ck
でtock, tuckに一致しますがtack, tickには一致しません。
繰り返し
{n} 直前の文字または式 n 個に一致します。たとえば、fe{2}d で feed に一致し ますが fedには一致しません。
{n,} 直前の文字または式 n 個以上という条件が一致する限り検索します。たとえ
ば、a{1,}で a, aa, aaa, …に一致します。最長一致をします。
{n, m} 直前の文字または式 n~m 個に一致します。たとえば、10{1,3}で 10、100、
1000に一致します。
@ 直前の文字または式を 1個以上という条件に一致します。たとえば、lo@t で lot や loot に一致します。最短一致をします。
*ワイルドカードでは大小文字の区別はできません。A と a を検索するときは[Aa]と します。
*{1,}と@は似ていますが、{1,}は条件が一致する限り最長の文字列を検索し、@は条 件が一致する最短の文字列を検索します。そこで、n で始まる単語を検索するときは 検索式を<n[a-z]{1,}とします。(検索式をn[a-z]@とすると nの後の1文字で一致を終 了します。)一方、n で終わる文字列を検索するときは、たとえば検索式を[a-z]@n>
のようにします。(検索式を[a-z]{1,}n>とすると、[a-z]{1,}がnを含めた最長一致をし てしまい、さらにその後のnを検索するために一致しません。)
検索式 テキスト
<n[a-z]{1,} no, not, nation, in, sign
<n[a-z]@ no, not, nation, in, sign [a-z]{1,}n> no, not, nation, in, sign
77 [a-z]@n> no, not, nation, in, sign
エスケープ文字
特殊文字の検索:(, ), [, ], {, }, ?, !, *, ¥を探すときは,その前に¥をつけてエスケープし ます。たとえば¥?でクエスチョンマークを検索します。(先のリテラル検索ではエス ケープの必要はありません。)
結果:ワイルドカード:w?s
1 In the beginning God created the heavens and the earth.
2 The earth was without form, and void; and darkness was on the face of the deep.
And the Spirit of God was hovering over the face of the waters.
(b) ワイルドカード置換
結果:ワイルドカード:w?s=>@
1 In the beginning God created the heavens and the earth.
2 The earth @ without form, and void; and darkness @ on the face of the deep. And the Spirit of God @ hovering over the face of the waters.
ワイルドカードによる後方参照は(...)と「¥数字」を使います。数字は検索文字列の (...)の左からの順番に対応します。
結果:ワイルドカード:(w?s)=>[[¥1]]
1 In the beginning God created the heavens and the earth.
2 The earth [[was]] without form, and void; and darkness [[was]] on the face of the deep. And the Spirit of God [[was]] hovering over the face of the waters.
このように後から検索文字列の一部を参照することを「後方参照」back referenceと呼 びます。ワイルドカードでは「¥」を使い、正規表現では「$」を使います。TEXTOS ではワイルドカードでも「$」を使うことができます。
(c) TEXTOSの拡張ワイルドカード
以下はTEXTOSに固有のワイルドカードです。
¥d 数字[0-9]
¥D 数字以外[!0-9]
78
¥s 空白文字(スペース、タブ、改行) [ ¥t¥n]
¥S 空白文字以外(スペース、タブ、改行)[! ¥t¥n]
¥w 単語に使用される文字(1文字と一致します。[A-Za-z_0-9])
¥W 単語に使用される文字以外(1文字[!A-Za-z_0-9])と一致します。
¥l 西欧語単語文字[a-zA-Z¥xC0-¥xD6¥xD8-¥xF6¥xF8-¥xFF]
¥L 西欧語単語文字以外[^a-zA-Z¥xC0-¥xD6¥xD8-¥xF6¥xF8-¥xFF]
¥i キリル文字
¥I キリル文字以外
¥g ギリシャ文字
¥G ギリシャ文字以外
¥e ハングル
¥E ハングル以外
¥y 統合漢字
¥Y 統合漢字以外
¥v 母音文字
¥V 母音文字以外
¥c 子音文字
¥C 子音文字以外
¥h ひらがな[ぁ-んー]
¥H ひらがな以外[^ぁ-んー]
¥k カタカナ[ァ-ンー]
¥K カタカナ以外[^ァ-ンー]
¥z 漢字[¥u4E00-¥uFA6A々〆]
¥Z 漢字以外[^¥u4E00-¥uFA6A々〆]
¥j 日本語文字[¥u3041-¥uFA6A々〆]
¥J 日本語文字以外(1文字[^¥u3041-¥uFA6A々〆])
入力文:
次は『旧約聖書』の第1の書『創世記』の第一章第一節「初めに、神は天地を創造さ れた」In the beginning God created the heaven and the earth.のラテン語、中世スペイン語、
現代スペイン語の訳である。
・ラテン語:In principio creavit Deus caelum et terram.
・中世スペイン語:En el prinçipio crio el señor los çielos & la tierra
・現代スペイン語:En el principio creó Dios los cielos y la tierra.
79
結果:ワイルドカード<¥c{1,}(<:単語境界、¥c:子音)
次は『旧約聖書』の第1の書『創世記』の第一章第一節「初めに、神は天地を創造さ れた」In the beginning God created the heaven and the earth.のラテン語、中世スペイン語、
現代スペイン語の訳である。
・ラテン語:In principio creavit Deus caelum et terram.
・中世スペイン語:En el prinçipio crio el señor los çielos & la tierra
・現代スペイン語:En el principio creó Dios los cielos y la tierra.
(d) コード
Sub ■検索置換分析()
検索置換式$ = Split(txt検索置換式, vbCrLf)
ReDim 検索$(UBound(検索置換式$)), 置換$(UBound(検索置換式$))
If chk新文書 s Then ●新文書
Select Case cbo検索.ListIndex 'コンボボックスでケースを選択
Case 0, 1: ●ワード検索置換式: ▼ワード検索置換
Case 2, 3: ●文字列検索置換式: ▼文字列検索置換
Case 4, 5, 6, 7:
●文字列検索置換式
選択範囲$ = Replace(Selection.Text, vbTab, " ") 'タブ→空白 段落配列$ = Split(選択範囲$, vbCr) '改行で分けた配列 obj正規表現.IgnoreCase = Not chk大小文字区別
obj連想配列.RemoveAll '連想配列のキーとアイテムを削除
段落番号& = 0
If cbo検索.ListIndex = 4 Then ▼検索式頻度 If cbo検索.ListIndex = 5 Then ▼鍵語頻度 If cbo検索.ListIndex = 6 Then ▼鍵語外置 If cbo検索.ListIndex = 7 Then ▼鍵語内置 End Select
End Sub
コンボボックスの選択を使って、全体を「ワード検索置換」(「リテラル検索置換」
80
と「ワイルドカード検索置換」)、「文字列検索置換」(「単純検索置換」と「正規 表現検索置換」)、「分析」(「検索式頻度」「鍵語頻度」「鍵語外置」「鍵語内置)
に分けます。「分析」では選択範囲や大小文字区別、連想配列、段落番号の初期化を します。
Sub ●ワード検索置換式()
For i = 0 To UBound(検索置換式$)
If InStr(検索置換式$(i), "=>") Then '置換式ならば…
検索$(i) = Left$(検索置換式$(i), InStr(検索置換式$(i), "=>") - 1) 置換$(i) = Mid$(検索置換式$(i), InStr(検索置換式$(i), "=>") + 2) Else '検索式ならば…
検索$(i) = 検索置換式$(i) End If
Next End Sub
Wordの書式を保つ検索・置換をするとき、テキストボックス内の検索置換式ならば、
「=>」がある置換式ならば「=>」の前後で、検索$と置換$を切り出します。「=>」が ない検索式ならば検索置換式を検索$に代入します。
Sub ▼ワード検索置換()
Selection.Find.ClearFormatting '検索初期化
Selection.Find.Replacement.ClearFormatting '置換初期化
With Selection.Find '選択範囲検索
.Replacement.Highlight = chk蛍光色 '置換蛍光ペン
If chk文字色 Then .Replacement.Font.Color = BGR$(txt文字色値)
If chk下線色 Then
.Replacement.Font.Underline = wdUnderlineWavy
.Replacement.Font.UnderlineColor = BGR$(txt下線色値) End If
.Replacement.Font.Bold = chk太字
.MatchWildcards = CBool(cbo検索.ListIndex = 1) 'ワイルドカード
.MatchCase = IIf(cbo検索.ListIndex = 1, True, chk大小文字区別) '大小文字区別
81 .Format = True '書式を含む
.MatchWholeWord = False '完全単語一致をしない .MatchByte = False '全角半角文字を区別しない .MatchPhrase = False '単語間の空白文字を無視しない .MatchSoundsLike = False '類似単語検索をしない .MatchFuzzy = False '曖昧検索をしない
.MatchAllWordForms = False '活用形検索をしない
.Wrap = wdFindStop '末尾で検索終了 End With
For i = 0 To UBound(検索$) If 検索$(i) = "" Then Exit For
Selection.Find.Text = 検索$(i)
Selection.Find.Replacement.Text = 置換$(i)
Selection.Find.Execute Replace:=wdReplaceAll '全置換 Next
Selection.Find.ClearFormatting '検索初期化
Selection.Find.Replacement.ClearFormatting '置換初期化 End Sub
全体は、検索・置換のフォーマットを初期化し、選択範囲で検索された対象について、
置換の方法を設定し、1回以上の検索・置換を実行し、最後にもう一度検索・置換の フォーマットの初期化します。
Function 拡張ワイルドカード$(ByVal w$)
w$ = Replace(w$, "¥¥", "!123") '¥¥をエスケープ
w$ = Replace(w$, "¥$", "@@!!") '$をエスケープ
w$ = Replace(w$, "(^|$|¥n)", "^13") '改行コードをワイルドカード式に w$ = Replace(w$, "@@!!", "$") '$を復元
w$ = Replace(w$, "¥t", "^9") 'タブコードをワイルドカード式に
82
w$ = Replace(w$, ".*", "*") '任意の文字 0個以上(最大一致)
w$ = Replace(w$, "¥.", "@@!!") '.をエスケープ
w$ = Replace(w$, ".", "?") '正規表現の任意の1文字をワイルドカード式に w$ = Replace(w$, "@@!!", ".") '.を復元
w$ = Replace(w$, "¥&", "@@!!") '&をエスケープ w$ = Replace(w$, "&", "¥l+") '単語文字 1以上 w$ = Replace(w$, "@@!!", "&") '&を復元
w$ = Replace(w$, "¥+", "@@!!") '+をエスケープ
w$ = Replace(w$, "+", "{1,}") '任意1文字をワイルドカード式に w$ = Replace(w$, "@@!!", "+") '+を復元
w$ = Replace(w$, "¥w", "[A-Za-z0-9_]") '英数字 w$ = Replace(w$, "¥W", "[!A-Za-z0-9_]") '英数字以外
w$ = Replace(w$, "¥d", "[0-9]") '数字 w$ = Replace(w$, "¥D", "[!0-9]") '数字以外
w$ = Replace(w$, "¥l", "[a-zA-Z¥xC0-¥xD6¥xD8-¥xF6¥xF8-¥xFF]") '拡張ラテン文字 w$ = Replace(w$, "¥L", "[!a-zA-Z¥xC0-¥xD6¥xD8-¥xF6¥xF8-¥xFF]") '拡張ラテン文字 以外
w$ = Replace(w$, "¥i", "[" & ChrW(&H400) & "-" & ChrW(&H52F) & "]") '拡張キリル文字
w$ = Replace(w$, "I", "[!" & ChrW(&H400) & "-" & ChrW(&H52F) & "]") '拡張キリル文字以外
w$ = Replace(w$, "¥g", "[" & ChrW(&H370) & "-" & ChrW(&H3FF) _ & ChrW(&H1F70) & "-" & ChrW(&H1F73) & "]") 'ギリシャ文字 w$ = Replace(w$, "¥G", "[!" & ChrW(&H370) & "-" & ChrW(&H3FF) _ & ChrW(&H1F70) & "-" & ChrW(&H1F73) & "]") 'ギリシャ文字
w$ = Replace(w$, "¥e", "[" & ChrW(&HAC00) & "-" & ChrW(&HD7AF) & "]") 'ハングル
w$ = Replace(w$, "¥E", "!" & ChrW(&HAC00) & "-" & ChrW(&HD7AF) & "]")
83 'ハングル以外
w$ = Replace(w$, "¥y", "[" & ChrW(&H3300) & "-" & ChrW(&H9FAF) & "]")
'CJK互換漢字、統合漢字、漢字拡張文字
w$ = Replace(w$, "¥Y", "[!" & ChrW(&H3300) & "-" & ChrW(&H9FAF) & "]")
'CJK互換漢字、統合漢字、漢字拡張文字以外
w$ = Replace(w$, "¥v", "[AEIOUaeiou" _
& ChrW(&HC0) & ChrW(&HC1) & ChrW(&HC2) _
& ChrW(&HC8) & ChrW(&HC9) & ChrW(&HCA) & ChrW(&HCB) _ & ChrW(&HCC) & ChrW(&HCD) & ChrW(&HCE) & ChrW(&HCF) _ & ChrW(&HD2) & ChrW(&HD3) & ChrW(&HD4) & ChrW(&HD5) _ & ChrW(&HD9) & ChrW(&HDA) & ChrW(&HDB) & ChrW(&HDC) _
& ChrW(&HE0) & ChrW(&HE1) & ChrW(&HE2) & ChrW(&HE3) & ChrW(&HE4) _ & ChrW(&HE8) & ChrW(&HE9) & ChrW(&HEA) & ChrW(&HEB) _
& ChrW(&HEC) & ChrW(&HED) & ChrW(&HEE) & ChrW(&HEF) _
& ChrW(&HF2) & ChrW(&HF3) & ChrW(&HF4) & ChrW(&HF5) & ChrW(&HF6) _ & ChrW(&HF9) & ChrW(&HFA) & ChrW(&HFB) & ChrW(&HFC) & "]") '母音文 字
w$ = Replace(w$, "¥V", "[!AEIOUaeiou" _
& ChrW(&HC0) & ChrW(&HC1) & ChrW(&HC2) _
& ChrW(&HC8) & ChrW(&HC9) & ChrW(&HCA) & ChrW(&HCB) _ & ChrW(&HCC) & ChrW(&HCD) & ChrW(&HCE) & ChrW(&HCF) _ & ChrW(&HD2) & ChrW(&HD3) & ChrW(&HD4) & ChrW(&HD5) _ & ChrW(&HD9) & ChrW(&HDA) & ChrW(&HDB) & ChrW(&HDC) _
& ChrW(&HE0) & ChrW(&HE1) & ChrW(&HE2) & ChrW(&HE3) & ChrW(&HE4) _ & ChrW(&HE8) & ChrW(&HE9) & ChrW(&HEA) & ChrW(&HEB) _
& ChrW(&HEC) & ChrW(&HED) & ChrW(&HEE) & ChrW(&HEF) _
& ChrW(&HF2) & ChrW(&HF3) & ChrW(&HF4) & ChrW(&HF5) & ChrW(&HF6) _ & ChrW(&HF9) & ChrW(&HFA) & ChrW(&HFB) & ChrW(&HFC) & "]") '母音文 字以外
w$ = Replace(w$, "¥c", "[BCDFGHJ-NP-TV-Zbcdfghj-np-tv-z" _
& ChrW(&HC7) & ChrW(&HD1) & ChrW(&HDF) & ChrW(&HEF) & ChrW(&HF1) &
"]")
'子音文字
w$ = Replace(w$, "¥C", "[!BCDFGHJ-NP-TV-Zbcdfghj-np-tv-z" _
84
& ChrW(&HC7) & ChrW(&HD1) & ChrW(&HDF) & ChrW(&HEF) & ChrW(&HF1) &
"]")
'子音文字以外
w$ = Replace(w$, "¥h", "[ぁ-ゞ]") 'ひらがな w$ = Replace(w$, "¥H", "[!ぁ-ゞ]") 'ひらがな以外 w$ = Replace(w$, "¥k", "[ァ-ヴー]") 'カタカナ w$ = Replace(w$, "¥K", "[!ァ-ヴー]") 'カタカナ以外 w$ = Replace(w$, "¥z", "[一-鶴]") '漢字
w$ = Replace(w$, "¥Z", "[!一-鶴]") '漢字以外
w$ = Replace(w$, "¥j", "[ぁ-ゞァ-ヾ一-鶴]") '日本語文字 w$ = Replace(w$, "¥J", "[!ぁ-ゞァ-ヾ一-鶴]") '日本語文字以外
w$ = Replace(w$, "!123", "¥¥") '¥¥を復元
拡張ワイルドカード$ = w$ '返り値 End Function