→2022/11/2 正規表現 初歩
>Kirari1192 |
>Kirari1192 |
||
186行目: | 186行目: | ||
</div></div> | </div></div> | ||
=== 2022/ | === 2022/11/2 正規表現 初歩 === | ||
貴職は何かのWikiのあるページから一定の条件に合う名前を探したいとするナリよ<br> | |||
例えば[[唐澤貴洋|唐澤]]で始まって[[唐澤洋|洋]]で終わるような名前ナリ<ref>現在MediaWikiには正規表現検索機能は無いので対象として使いやすい名前からとしました。貴洋なんて名前を付けた厚子が悪い</ref> | |||
そういう時は正規表現(regular expression)を使って検索出来るナリ<br> | |||
〇〇で始まって⚫⚫で終わるという指定の他繰り返し回数も指定できる、これはいい。 | |||
正規表現において、指定した表現に合致することをマッチする、と言いますを<br> | |||
以下、Pythonでは<code>import re</code>があるものとしますを とりあえず取り急ぎ | |||
==== リテラル ==== | |||
まずは正規表現の基本から始めますを リテラルは特殊ではない文字か(正しく)エスケープされている文字列を指しますを<br> | |||
Pythonでは<code>re.match</code>、Kotlinでは<code>toRegex().matches()</code>でマッチを試すことが出来るなりを またmatchの後を見ると何とマッチしたかが分かる、これはいい | |||
(Python) | |||
>>> re.match(r'唐澤洋', '唐澤貴洋') | |||
>>> re.match(r'唐澤洋', '唐澤洋') | |||
<re.Match object; span=(0, 3), match='唐澤洋'> | |||
(Kotlin) | |||
>>> "唐澤洋".toRegex().matches("唐澤貴洋") | |||
res0: kotlin.Boolean = false | |||
>>> "唐澤洋".toRegex().matches("唐澤洋") | |||
res1: kotlin.Boolean = true | |||
Pythonでは<code>re.Match object</code>が、Kotlinでは<code>= true</code>と出ている方がマッチしている方ですを<br> | |||
これを見て分かる通り、唐澤貴洋の方にはマッチしていないことは明白。これはいけない | |||
==== 文字集合 ==== | |||
[[唐澤貴洋|????]]「唐澤貴洋にもマッチさせろナリ!」<br> | |||
ヤーマン「駄目です」<br> | |||
[[唐澤貴洋|????]]「あブ」 | |||
とはならないのでだから安心だから安心だから安心 | |||
マッチさせる文字集合について考えるナリ<br> | |||
文字集合というのはマッチさせる(させない)文字の範囲のことですを<br> | |||
当然全ての文字にマッチというのも存在するナリ | |||
例えば「貴」と「洋」だけとしたりとか、もしくは[[山岡裕明|「裕」と「明」]]<ref>淫乱乳首はお呼びでないので答えだけ書きます。<code>[^裕明]</code>とすればできます。<code>^</code>は指定した文字集合を反転するという意味になります。誰とは言わんが早く解放しろ乳首</ref>以外にマッチさせるということができますを<br> | |||
「貴」と「洋」のように文字集合を指定するなら角括弧で囲んで<code>[貴洋]</code>とすれば良いですを<br> | |||
AからZまで全部対象に入れたいのであればハイフンを使って<code>[A-Z]</code>のように表現出来るナリ<br> | |||
当然<code>[A-Z貴洋]</code><ref>この例ではAからZまたは貴洋から一文字の合計一文字だが、<code>[A-Z][貴洋]</code>とすると、AからZまでの一文字と貴洋のいずれか一文字の合計2文字にマッチする。集合一個が文字に相当するので注意</ref>のように合体させることも出来るナリよ なおA-Zは一体なので<code>[A-貴Z洋]</code>のようにごちゃまぜにしては別の意味になってしまう。これはいけない<ref>ここでのハイフンは<strong>Unicodeコードポイント上での</strong>範囲を指すため、こうしてしまうとA(U+0041)から貴(U+8CB4)という相当広い範囲に加えてZ(U+005A)と洋(U+6D0B)という"A-貴"の範囲に入るためほぼ無意味な指定が続くという構図になる。これはいけない</ref> | |||
これを踏まえて正規表現の途中に文字集合を入れるとこのようになるナリ | |||
(Python) | |||
>>> re.match(r'唐澤[貴洋]洋', '唐澤貴洋') | |||
<re.Match object; span=(0, 4), match='唐澤貴洋'> | |||
>>> re.match(r'唐澤[貴洋]洋', '唐澤洋') | |||
(Kotlin) | |||
>>> "唐澤[貴洋]洋".toRegex().matches("唐澤貴洋") | |||
res0: kotlin.Boolean = true | |||
>>> "唐澤[貴洋]洋".toRegex().matches("唐澤洋") | |||
res1: kotlin.Boolean = false | |||
全ての文字<ref>(ここでは扱わない)フラグによるが、改行文字も含む</ref>にマッチさせたい時は<code>.</code>一文字で出来るナリ | |||
(Python) | |||
>>> re.match(r'唐澤.洋', '唐澤貴洋') | |||
<re.Match object; span=(0, 4), match='唐澤貴洋'> | |||
>>> re.match(r'唐澤.洋', '唐澤洋') | |||
(Kotlin) | |||
>>> "唐澤.洋".toRegex().matches("唐澤貴洋") | |||
res0: kotlin.Boolean = true | |||
>>> "唐澤.洋".toRegex().matches("唐澤洋") | |||
res1: kotlin.Boolean = false | |||
しかし今度は唐澤洋にマッチしないナリ | |||
==== 量化指定子 ==== | |||
[[唐澤貴洋|????]]「次は両者にマッチするようにするナリ、当職はどれを使えば良いナリか」 | |||
* <code>*</code> - 0回以上無制限 | |||
* <code>+</code> - 1回以上無制限 | |||
* <code>?</code> - 0回以上1回以下 | |||
* <code>{n}</code> - 丁度n回 | |||
* <code>{n,}</code> - n回以上無制限 | |||
* <code>{n,m}</code> - n回以上m回以下 | |||
[[唐澤貴洋|????]]「あブ」<sub>(シンキングタイム: 哀れなデブを横目に何を使うか考えてみよう)</sub> | |||
量化指定子は文字や文字集合などの後に付けるナリ またmやnは実際に正規表現に使う時は数値(例: <code>{334,40298}</code>)に置き換える必要があるナリ | |||
正解発表ナリ<br> | |||
最短という面では正解は<code>?</code>ですを 「0回以上1回以下」は「存在してもしなくても良い」と考えて欲しいですを(以下Kotlin省略) | |||
(Python) | |||
>>> re.match(r'唐澤.?洋', '唐澤貴洋') | |||
<re.Match object; span=(0, 4), match='唐澤貴洋'> | |||
>>> re.match(r'唐澤.?洋', '唐澤洋') | |||
<re.Match object; span=(0, 3), match='唐澤洋'> | |||
>>> re.match(r'唐澤.?洋', '唐澤死洋') | |||
<re.Match object; span=(0, 4), match='唐澤死洋'> | |||
この場合、.に?の量化指定子を使用したので唐澤と洋の間にどんな文字でも入れられますを | |||
どんな長さの文字列が入っても良いなら<code>*</code>を使いますを | |||
(Python) | |||
>>> re.match(r'唐澤.*洋', '唐澤貴洋ナイフで滅多刺しにして殺す。洋、お前もだ') | |||
<re.Match object; span=(0, 19), match='唐澤貴洋ナイフで滅多刺しにして殺す。洋'> | |||
>>> re.match(r'唐澤.*洋', '唐澤洋') | |||
<re.Match object; span=(0, 3), match='唐澤洋'> | |||
>>> re.match(r'唐澤.*洋', '唐澤死洋') | |||
<re.Match object; span=(0, 4), match='唐澤死洋'> | |||
量化指定子を使いつつ最短でマッチさせたい場合は、量化指定子に続けて<code>*</code>を付けるナリよ (唐澤貴洋のみにマッチすることに注目) | |||
(Python) | |||
>>> re.match(r'唐澤.*?洋', '唐澤貴洋ナイフで滅多刺しにして殺す。洋、お前もだ') | |||
<re.Match object; span=(0, 4), match='唐澤貴洋'> | |||
==== まとめ ==== | |||
OSS部員が疲れたと言うのでここで終わりになってしまうナリが、正規表現の基礎中の基礎はなんとか理解できると思うナリ<br> | |||
分からないことがあれば議論ページで質問してくれれば<del>OSS部員に丸投げして</del>答えるナリ | |||
正規表現はもっと奥深い世界なので興味を持った芋はもっと調べてみることを切に望む<ref>取材注: なお当の部員はHTMLの正規表現とHTMLの2つとにらめっこして頭の中でマッチとか修正したり、HTMLやその他コードを見て正しく切り出せるであろう正規表現で一発で書けるらしい。バケモンか?</ref>。 | |||
== 脚注 == | == 脚注 == | ||
<references /> | <references /> |