正規表現。
成果物
情報源
正規表現については以下を参照した。感謝。
- https://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
- https://www.mnet.ne.jp/~nakama/
- https://rdr.utopiat.net/docs/reference/etc/regexpsyntax.htm
- https://qiita.com/AquaMeria/items/cf22ba6750a3812f6566
構文
select '文字列' regexp 'パターン';
select regexp('パターン','文字列');
正規表現
文字列から指定パターンに一致するか判定する。like
やglob
などのワイルドカードよりも遥かに多く複雑なパターンを指定できる。
じつは正規表現にはいくつかの種類がある。
SQLite3の公式からは正規表現の文法についての情報を見つけられなかった。まずはネットで正規表現について調べて、それをSQLite3で使えるかどうか試していく。おそらくPerlの正規表現
が使えると期待する。
メタ文字
. ^ $ [ ] * + ? | ( )
メタ文字のエスケープ
\
(バックスラッシュ)をメタ文字の前につける\
自体のエスケープも\\
で可能
メタ文字
隣接パターンの位置指定
メタ文字 | 意味 |
---|---|
^abc |
前方一致。先頭がabc の文字列で始まる |
abc$ |
後方一致。末尾がabc の文字列で終わる |
^abc$ |
完全一致。先頭と末尾の間がabc |
.*abc.* |
部分一致。 |
特殊エスケープ
特殊エスケープ | 意味 |
---|---|
\b |
スペースなどの単語の区切り |
\B |
\b以外の文字 |
\cA |
Ctrl-A |
\d |
任意の数値([0-9] と同じ) |
\D |
数値以外の文字([^0-9] と同じ) |
\f |
フォームフィード文字 |
\n |
改行文字 |
\r |
復帰文字 |
\s |
区切り文字(スペース、タブ、改行)([ \f\n\r\t\v] と同じ) |
\S |
\s 以外の1文字([^ \n\r\f\t] と同じ) |
\t |
タブ文字 |
\v |
垂直タブ文字 |
\w |
英数文字([A-Za-z0-9_] と同じ) |
\W |
\w 以外の文字 |
\1 |
1番目の(...) にマッチした文字列 |
\o033 |
8進数で033にあたる文字 |
\x1b |
16進数で1bにあたる文字 |
\その他 |
その他の文字自身 |
文字種
メタ文字 | 意味 |
---|---|
. |
任意の1字 |
[abc] |
候補。a ,b ,c のいずれか1字 |
[^abc] |
否定。a ,b ,c 以外のいずれか1字 |
[a-z] |
範囲。a 〜z の間にあるいずれか1字 |
前のパターンのくりかえし数を指定
メタ文字 | 意味 |
---|---|
? |
0回か1回 |
+ |
1回以上 |
* |
0回以上 |
{3} |
きっかり3回 |
{3,} |
3回以上 |
{3,7} |
3回以上7回以下 |
グループ化
メタ文字 | 意味 |
---|---|
(abc) |
abc の文字列(各文字でなく文字列) |
論理演算
メタ文字 | 意味 |
---|---|
`(abc | def)| OR。 abcまたは def` |
(?=abc) |
直後にabc がある(肯定的先読み) |
(?!abc) |
直後にabc がなる(否定的先読み) |
(?<=abc) |
直前にabc がある(肯定的後読み) |
(?<!abc) |
直前にabc がなる(否定的後読み) |
やってみる
select '2000-01-01' regexp '\d{4}-\d{2}-\d{2}';
1
メタ文字のエスケープ
.
select 'etc...' regexp 'etc.\.\.';
1
select 'etc!!!' regexp 'etc.\.\.';
0
select 'etc!!!' regexp 'etc...';
1
^
select '2^4=16' regexp '2\^4=16';
1
select '2^4=16' regexp '2^4=16';
0
$
select '$100' regexp '\$100';
1
select '$100' regexp '$100';
0
[
, ]
select '[123]' regexp '\[123\]';
0
select '[123]' regexp '[123]';
0
(
, )
select '(123)' regexp '\(123\)';
0
select '(123)' regexp '(123)';
0
*
select '***' regexp '\*\*\*';
1
select '***' regexp '***';
Error: ICU error: uregex_open(): U_REGEX_RULE_SYNTAX
+
select '1+2' regexp '1\+2';
1
select '1+2' regexp '1+2';
0
?
select 'what?' regexp 'what\?';
1
select 'what?' regexp 'what?';
0
\|
select 'A|B' regexp 'A\|B';
1
select 'A|B' regexp 'A|B';
0
\
select '\s' regexp '\\s';
1
select '\s' regexp '\s';
0
隣接パターンの位置指定
前方一致。
select 'abc123' regexp '^abc.*';
1
後方一致。
select 'abc123' regexp '.*123$';
1
完全一致。
select 'abc123' regexp 'abc123'; select 'abc123' regexp '^abc123$';
1 1
部分一致。
select 'abc123' regexp '.*abc.*'; select '123abc' regexp '.*abc.*'; select '12abc3' regexp '.*abc.*';
1 1 1
文字種パターン。
select '12abc3' regexp '.*[a-zA-Z]+.*';
1
グループ化
select 'abc2000年01月02日def' regexp '.*(\d{4}年\d{2}月\d{2}日).*';
1
特殊エスケープ
\b
select ' ' regexp '\b';
0
select '\' regexp '\b';
0
どうやら\b
は使えないらしい。
\B
select 'a' regexp '\b';
0
select ' ' regexp '\b';
0
どうやら\B
は使えないらしい。
\cA
そもそも、Ctrl
制御コードをどうやって入力するの?
たとえば改行コードは16進数で0x0A
、10進数で10
。制御コードでは^J
、正規表現では^
を\c
で表す。つまり\cJ
。
select char(0x0A) regexp '\cJ';
1
もっとも、現代でも使うような制御コードは改行やタブなどであり、それらは\s
でまとめて表現できるはず。
\d
数字。[0-9]
と同じ。
select '123' regexp '\d+';
1
select '123a' regexp '\d+';
0
\D
数字以外。[^0-9]
と同じ。
select 'abc' regexp '\D+';
1
select '123' regexp '\D+';
0
\f
フォームフィード文字。プリンタでは次のページを給紙する。
select char(0x0C) regexp '\f';
1
select char(0x0C) regexp '\cL';
1
\n
改行コード。
select 'A' || char(0x0A) || 'B' regexp 'A\nB';
1
\r
復帰コード。
select 'A' || char(0x0D) || 'B' regexp 'A\rB';
1
select 'A' || char(0x0D) || char(0x0A) || 'B' regexp 'A\r\nB';
1
\s
空白文字(区切り文字(スペース、タブ、改行))。[ \f\n\r\t\v]
と同じ。
select 'A B' regexp 'A\sB'; select 'A' || char(0x0C) || 'B' regexp 'A\sB'; select 'A' || char(0x0A) || 'B' regexp 'A\sB'; select 'A' || char(0x0D) || 'B' regexp 'A\sB'; select 'A' || char(0x09) || 'B' regexp 'A\sB'; select 'A' || char(0x0B) || 'B' regexp 'A\sB';
1
全角スペースも真になった。
select 'A B' regexp 'A\sB';
1
他は偽。
select 'あ' regexp '\s';
0
\S
区切り文字(スペース、タブ、改行)以外。[^ \f\n\r\t\v]
と同じ。
select 'A B' regexp 'A\SB'; select 'A' || char(0x0C) || 'B' regexp 'A\SB'; select 'A' || char(0x0A) || 'B' regexp 'A\SB'; select 'A' || char(0x0D) || 'B' regexp 'A\SB'; select 'A' || char(0x09) || 'B' regexp 'A\SB'; select 'A' || char(0x0B) || 'B' regexp 'A\SB';
0
全角スペースも対象外。
select 'A B' regexp 'A\SB';
0
他は真。
select 'あ' regexp '\S';
1
\t
select 'A' || char(0x09) || 'B' regexp 'A\tB';
1
\v
select 'A' || char(0x0B) || 'B' regexp 'A\vB';
1
\w
英数字。[0-9A-Za-z_]
と同じ。
select 'a' regexp '\w';
1
select 'Z' regexp '\w';
1
select '3' regexp '\w';
1
select '_' regexp '\w';
1
select '$' regexp '\w';
0
\W
英数字以外。[^0-9A-Za-z_]
と同じ。
select 'a' regexp '\W';
0
select 'Z' regexp '\W';
0
select '3' regexp '\W';
0
select '_' regexp '\W';
0
select '$' regexp '\W';
1
\o
8進数。これ、効いてないと思われる。
select 'o001' regexp '\o001';
1
select '001' regexp '\o001';
0
select '1' regexp '\o001';
0
\x
16進数。これ、効いてないと思われる。
select 'x0F' regexp '\x0F';
0
select '0x0F' regexp '\x0F';
0
select 'x0F' regexp '\x0F';
0
select '15' regexp '\x0F';
0
何一つヒットさせられなかった。
\数
(後方参照)
select '11' regexp '(\d)\1';
1
select '1a1' regexp '(\d)a\1';
1
\その他
その他の文字自身。
select 'c' regexp '\c';
1
\a
はなぜか一致せず。特殊な意味があるのか?
select 'a' regexp '\a';
0
ネットには^
,$
の代わりに\A
,\z
を使うようなことが書いてあった。それか? でも大文字だし。
select 'a' regexp '\aa';
0
やはり違う。\A
とすべき。つまり\a
は何か別の特殊な意味になるようだ。情報がない……。
select 'a' regexp '\Aa';
1
e
でもヒットせず。
select 'e' regexp '\e';
0
select 'g' regexp '\g';
1
select 'h' regexp '\h';
0
select 'i' regexp '\i';
1
select 'j' regexp '\j';
1
select 'k' regexp '\k';
Error: ICU error: uregex_open(): U_REGEX_INVALID_CAPTURE_GROUP_NAME
上記の英字はすべて特殊エスケープ以外だと思うのだが、それぞれ反応が違う……。もうわけわかんない。公式さん仕様ください。
文字種
.
任意の1字。
select 'a' regexp '.';
1
select 'aa' regexp '.';
0
任意の長さをした任意の字。
select 'aaaaa' regexp '.*';
1
[]
いずれかの1字。
select 'a' regexp '[abc]';
1
select 'z' regexp '[abc]';
0
[^]
いずれかの1字以外。
select 'a' regexp '[^abc]';
0
select 'z' regexp '[^abc]';
1
[-]
指定した字の範囲にあるいずれかの字。文字コードポイントの範囲指定。
select 'k' regexp '[a-z]';
1
select 'A' regexp '[a-z]';
0
前のパターンのくりかえし数を指定
?
0回か1回。
select '' regexp 'a?'; select 'a' regexp 'a?'; select 'b' regexp 'a?'; select 'aaa' regexp 'a?';
1 1 0 0
select 'k' regexp '[a-z]?'; select 'A' regexp '[a-z]?';
1 0
select '' regexp '(abc)?'; select 'abc' regexp '(abc)?'; select 'def' regexp '(abc)?';
1 1 0
+
1回以上。
select '' regexp 'a+'; select 'a' regexp 'a+'; select 'b' regexp 'a+'; select 'aaa' regexp 'a+';
0 1 0 1
select 'k' regexp '[a-z]+'; select 'A' regexp '[a-z]+'; select 'kkk' regexp '[a-z]+';
1 0 1
select '' regexp '(abc)+'; select 'abc' regexp '(abc)+'; select 'def' regexp '(abc)+'; select 'abcabc' regexp '(abc)+'; select 'abcdef' regexp '(abc)+'; select 'defabc' regexp '(abc)+'; select 'abcdef' regexp '(abc)+.*'; select 'abcabcdef' regexp '(abc)+.*';
0 1 0 1 0 0 1 1
*
0回以上。
select '' regexp 'a*'; select 'a' regexp 'a*'; select 'b' regexp 'a*'; select 'aaa' regexp 'a*';
1 1 0 1
select 'k' regexp '[a-z]*'; select 'A' regexp '[a-z]*'; select 'kkk' regexp '[a-z]*';
1 0 1
select '' regexp '(abc)*'; select 'abc' regexp '(abc)*'; select 'def' regexp '(abc)*'; select 'abcabc' regexp '(abc)*'; select 'abcdef' regexp '(abc)*'; select 'defabc' regexp '(abc)*'; select 'abcdef' regexp '(abc)*.*'; select 'abcabcdef' regexp '(abc)*.*';
1 1 0 1 0 0 1
{N}
きっかり指定回数。
select '' regexp 'a{1}'; select 'a' regexp 'a{1}'; select 'b' regexp 'a{1}'; select 'aaa' regexp 'a{1}'; select 'aaa' regexp 'a{3}';
0 1 0 0 1
select 'k' regexp '[a-z]{1}'; select 'A' regexp '[a-z]{1}'; select 'ghi' regexp '[a-z]{1}'; select 'ghi' regexp '[a-z]{3}';
1 0 0 1
select '' regexp '(abc){1}'; select 'abc' regexp '(abc){1}'; select 'abc' regexp '(abc){1}'; select 'def' regexp '(abc){1}'; select 'abcabc' regexp '(abc){1}'; select 'abcdef' regexp '(abc){1}'; select 'defabc' regexp '(abc){1}'; select 'abcdef' regexp '(abc){1}.*'; select 'abcabcdef' regexp '(abc){1}.*';
0 1 1 0 0 0 0 1 1
{N,}
指定回数以上。
select '' regexp 'a{1,}'; select 'a' regexp 'a{1,}'; select 'b' regexp 'a{1,}'; select 'aaa' regexp 'a{1,}'; select 'aaa' regexp 'a{4,}';
0 1 0 1 0
{N,M}
指定回数以内。
select '' regexp 'a{1,2}'; select 'a' regexp 'a{1,2}'; select 'b' regexp 'a{1,2}'; select 'aaa' regexp 'a{1,2}'; select 'aaa' regexp 'a{4,7}'; select 'aaa' regexp 'a{3,4}';
0 1 0 0 0 1
()
グループ化。
select 'aabc' regexp 'a(abc)'; select 'adef' regexp 'a(abc)';
1 0
任意の文字列があったりなかったり。
select 'a' regexp 'a(abc)?'; select 'aabc' regexp 'a(abc)?'; select 'adef' regexp 'a(abc)?';
1 1 0
(|)
いずれかの文字列。
select 'aabc' regexp 'a(abc|def)'; select 'adef' regexp 'a(abc|def)';
1 1
(?=)
, (?!)
, (?<=)
, (?<!)
先読み・後読みは使えないのか?
select 'abc' regexp '(?=abc)'; select 'abc' regexp '(?<=abc)'; select 'abc' regexp '(?!abc)'; select 'abc' regexp '(?<!abc)';
0 0 0 0
regexp()
関数
select regexp('\w+','abc');
1
判定・抽出・置換
ところで上記まではマッチするかの「判定」のみだった。ほかにもパターン箇所のみ「抽出」したり「置換」したい。それをSQLite3でできるか?
- http://tadasy.hateblo.jp/entry/20130308/1362718473
- https://stackoverflow.com/questions/38877856/replace-a-part-of-a-string-with-regexp-in-sqlite3
linuxのgrep
コマンドのように「抽出」もしたいのだが、方法が見つからず。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- SQLite 3.29.0
- MeCab 0.996ユーザ辞書
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux
前回まで
- SQLite3学習 俯瞰まとめ
- SQLite3学習 環境構築まとめ
- SQLite3学習 インタフェースまとめ(C言語、CLI、対話モード、Tcl...)
- SQLite3学習 ドットコマンドまとめ
- SQLite3学習 JSON拡張まとめ
- SQLite3学習 FTSまとめ(ICU, MeCab)
- SQLite3学習 再帰クエリ(WITH RECURSIVE)
- SQLite3学習 R-Treeモジュール
- SQLite3学習 Geopoly(2次元ベクタ画像の生成)
- SQLite3学習 拡張関数(generate_series)
- SQLite3学習 拡張ライブラリ数学関数(extension-functions.c)
- SQLite3学習 謎と名前
- SQL文の分類(DDL,DML,TCL,DCL)
- SQL構文 alter(rename)
- SQL構文 alter(add column)概要
- SQL構文 alter(add column)制約
- SQL構文 alter(add column)sqlite_master変更しても反映されない
- SQL構文 alter(add column)スキーマ再定義(テーブル再作成による定義変更)
- SQL構文 analyze
- SQL構文 attach/detach
- SQLite3構文 begin,end,commit,rollback,savepoint(deferred,immediate,exclusive)
- SQLite3構文 コメント
- SQLite3構文 create/drop
- SQLite3構文 index(create/drop)
- SQLite3構文 table(create/drop)
- SQLite3構文 列制約(default)
- SQLite3構文 列制約(collate)
- SQLite3構文 列制約(primary key)
- SQLite3構文 列制約(primary key)ベストプラクティス
- SQLite3構文 列制約(unique)
- SQLite3構文 列制約(not null)
- SQLite3構文 列制約(check)
- SQLite3構文 列制約(foreign key references)
- SQLite3構文 表制約(primary key, unique, check, foreign key)
- SQLite3でメタデータを取得する方法(DB名(スキーマ名)、テーブル名、列名、制約)
- SQLite3でTEMPの保存先を指定する
- SQLite3構文 delete
- SQLite3ビルド失敗(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
- SQLite3をソースからビルドする(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
- SQLite3構文 delete(limit offset, order by)
- SQLite3クエリプランニング(インデックスの働き)
- SQLite3構文 explain
- SQLite構文 expression
- SQLite構文 expression(リテラル)
- SQLite構文 expression(パラメータ)
- SQLite構文 expression(演算子)
- SQLite構文 expression(in 句)
- SQLite構文 expression(like 句)
- SQLite構文 expression(glob 句)