PostgreSQL正規表現の一般的な機能の概要

PostgreSQL正規表現の一般的な機能の概要

PostgreSQL正規表現の一般的な機能の概要

正規表現は、複雑なデータ処理を必要とするプログラムにとって、間違いなく非常に便利なツールです。この記事では、PostgreSQL のよく使用される正規表現関数とソース コード内のいくつかの関数について説明することに重点を置いています。

通常関連部分のディレクトリ構造

[root@localhost 正規表現]# pwd
/opt/hgdb-core/src/include/regex
[root@localhost 正規表現]# ll
合計40
-rw-r--r--。1 postgres postgres 3490 3月19日 19:00 regcustom.h
-rw-r--r--。1 postgres postgres 1332 3月19日 18:59 regerrs.h
-rw-r--r--。1 postgres postgres 6703 3月19日 19:00 regex.h
-rw-r--r--。1 postgres postgres 2353 3月19日 19:00 regexport.h
-rw-r--r--。1 postgres postgres 16454 3月19日 19:00 regguts.h

正規表現のコンパイル、マッチング、リリース、エラー情報関連のファイルについては後ほど詳しく紹介します

[root@localhost 正規表現]# pwd
/opt/hgdb-core/src/backend/regex
[root@localhost 正規表現]# ll reg*.c
-rw-r--r--。1 postgres postgres 55851 3月19日 19:00 regcomp.c
-rw-r--r--。1 postgres postgres 3671 3月19日 18:59 regerror.c
-rw-r--r--。1 postgres postgres 34873 3月19日 19:00 regexec.c
-rw-r--r--。1 postgres postgres 2123 3月19日 18:59 regfree.c
[root@localhost 正規表現]# 

組み込み関数はregexp.cに実装されています。

[root@localhost adt]# パスワード
/opt/hgdb-core/src/backend/utils/adt
[root@localhost adt]# ll regexp.c
-rw-r--r--。1 postgres postgres 34863 4月12日 02:29 regexp.c
[root@localhost adt]#

組み込み関数の宣言:

/* src/include/catalog/pg_proc.h */

DATA(挿入 OID = 2073 ( 部分文字列 PGNSP PGUID 12 1 0 0 0 fffftfi 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ textregexsubstr _null_ _null_ _null_ ));
DESCR("正規表現に一致するテキストを抽出");
DATA(挿入 OID = 2074 ( サブ文字列 PGNSP PGUID 14 1 0 0 0 fffftfi 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ "pg_catalog.substring($1, pg_catalog.similar_escape($2, $3))" _null_ _null_ _null_ ));
DESCR("SQL99 正規表現に一致するテキストを抽出");

DATA(挿入 OID = 2284 ( regexp_replace PGNSP PGUID 12 1 0 0 0 fffftfi 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ textregexreplace_noopt _null_ _null_ _null_ ));
DESCR("正規表現を使用してテキストを置換");
DATA(挿入 OID = 2285 ( regexp_replace PGNSP PGUID 12 1 0 0 0 fffftfi 4 0 25 "25 25 25 25" _null_ _null_ _null_ _null_ _null_ textregexreplace _null_ _null_ _null_ ));
DESCR("正規表現を使用してテキストを置換");

DATA(挿入 OID = 2763 ( regexp_matches PGNSP PGUID 12 1 1 0 0 fffftti 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_matches_no_flags _null_ _null_ _null_ ));
DESCR("正規表現に一致するすべてのグループを検索");
DATA(挿入 OID = 2764 ( regexp_matches PGNSP PGUID 12 1 10 0 0 fffftti 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_matches _null_ _null_ _null_ ));
DESCR("正規表現に一致するすべてのグループを検索");

DATA(挿入 OID = 2765 ( regexp_split_to_table PGNSP PGUID 12 1 1000 0 0 fffftti 2 0 25 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_table_no_flags _null_ _null_ _null_ ));
DESCR("パターンで文字列を分割");
DATA(挿入 OID = 2766 ( regexp_split_to_table PGNSP PGUID 12 1 1000 0 0 fffftti 3 0 25 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_table _null_ _null_ _null_ ));
DESCR("パターンで文字列を分割");

DATA(挿入 OID = 2767 ( regexp_split_to_array PGNSP PGUID 12 1 0 0 0 fffftfi 2 0 1009 "25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_array_no_flags _null_ _null_ _null_ ));
DESCR("パターンで文字列を分割");
DATA(挿入 OID = 2768 ( regexp_split_to_array PGNSP PGUID 12 1 0 0 0 fffftfi 3 0 1009 "25 25 25" _null_ _null_ _null_ _null_ _null_ regexp_split_to_array _null_ _null_ _null_ ));

パラメータの型と戻り値の型:

postgres=# select oid,typname from pg_type where oid = 25 or oid = 1009;
 oid | タイプ名 
------+---------
  25 | テキスト
 1009 | _テキスト
(2行)

substring(string from pattern) 関数は、POSIX 正規表現パターンに一致する文字列から部分文字列を抽出するメソッドを提供します。一致するものがない場合には NULL を返し、そうでない場合はパターンに一致したテキストの部分を返します。

regexp_replace(source, pattern, replacement [, flags ]) 関数は、POSIX 正規表現パターンに一致する部分文字列を新しいテキストに置き換える機能を提供します。

regexp_matches(string, pattern[, flags ]) 関数は、POSIX 正規表現パターンに一致するすべての部分文字列を含むテキストの配列を返します。
flags パラメータは、関数の動作を変更する 0 個以上の 1 文字のフラグを含むオプションのテキスト文字列です。 g フラグにより​​、文字列内の最初の一致だけでなくすべての一致が検索され、各一致が 1 行で返されます。

regexp_split_to_table(string, pattern[, flags ]) 関数は、POSIX 正規表現パターンを区切り文字として使用して文字列を分割します。返される結果は文字列です。 。

regexp_split_to_array (string, pattern[, flags ]) 関数は regexp_split_to_table と同じように動作しますが、結果をテキスト配列として返します。

具体的な使用方法についてはユーザーマニュアルを参照してください。

src/include/regex/regex.h

regex_t 構造体

/* 一番大事なのは、コンパイルされた RE (というか、そのフロントエンド) */
typedef構造体
{
 int re_magic; /* マジックナンバー */
 size_t re_nsub; /* 部分式の数 */
 long re_info; /* REに関する情報 */
#REG_UBACKREF 000001 を定義します
#REG_ULOOKAHEAD 000002 を定義します
#REG_UBOUNDS 000004 を定義します
#REG_UBRACES 000010 を定義します
#REG_UBSALNUM 000020 を定義します
#REG_UPBOTCH 000040 を定義します
#REG_UBBS 000100 を定義します
#REG_UNONPOSIX 000200 を定義します
#REG_UUNSPEC 000400 を定義します
#REG_UUNPORT 001000 を定義します
#REG_ULOCALE 002000 を定義します
#REG_UEMPTYMATCH 004000 を定義します
#REG_UIMPOSSIBLE 010000 を定義します
#REG_USHORTEST 020000 を定義します
 int re_csize; /* sizeof(文字) */
 char *re_endp; /* 下位互換性のためのクルージ */
 Oid re_collat​​ion; /* LC_CTYPE の動作を定義する照合順序 */
 /* 残りは隠された内部への不透明なポインタです */
 char *re_guts; /* `char *' は `void *' よりも移植性が高い */
 char *re_fns;
} 正規表現t;

コンパイルされた正規表現を保存する

regmatch_t 構造体

/* 結果の報告 (後でさらにフィールドを取得する可能性があります) */
typedef構造体
{
 regoff_t rm_so; /* 部分文字列の開始 */
 regoff_t rm_eo; /* 部分文字列の終了 */
} regmatch_t;

typedef long regoff_t;

メンバー rm_so は、ターゲット文字列内の一致するテキスト文字列の開始位置を格納し、rm_eo は終了位置を格納します。通常、このような構造のグループを配列の形式で定義します。

いくつかの主な関数の宣言があります:

/*
 * エクスポートされた関数のプロトタイプ
 */
外部 int pg_regcomp(regex_t *, const pg_wchar *, size_t, int, Oid);
外部 int pg_regexec(regex_t *, const pg_wchar *, size_t, size_t, rm_detail_t *, size_t, regmatch_t[], int);
外部 int pg_regprefix(regex_t *, pg_wchar **, size_t *);
外部 void pg_regfree(regex_t *);
extern size_t pg_regerror(int, const regex_t *, char *, size_t);
extern void pg_set_regex_collat​​ion(Oid 照合);

正規表現を処理するためによく使用される関数は、pg_regcomp()、pg_regexec()、pg_regfree()、および pg_regerror() です。

一般的な処理手順: 正規表現をコンパイルする pg_regcomp()、正規表現に一致する pg_regexec()、正規表現を解放する pg_regfree()。

pg_regerror(): regcomp または regexec の実行中にエラーが発生した場合、この関数を呼び出してエラー メッセージを含む文字列を返すことができます。

パラメータの説明

整数
pg_regcomp(regex_t *re,
   const chr *文字列, /* 正規表現文字列*/
   size_t len, /* 正規表現文字列の長さ*/
   intフラグ、
   OID照合

整数
pg_regexec(regex_t *re, /* regcomp関数でコンパイルされた正規表現*/
   const chr *文字列, /* 対象文字列*/
   size_t len, /* 対象文字列の長さ*/
   size_t search_start, /* 一致開始位置*/
   rm_detail_t *詳細, /* NULL */
   size_t nmatch、/* regmatch_t 構造体配列の長さ*/
   regmatch_t pmatch[], /* regmatch_t 型構造体配列、一致するテキスト文字列の位置情報を格納します*/
   int フラグ)

src/backend/utils/adt/regexp.c

/* 正規表現関数に関するすべてのオプション */
typedef 構造体 pg_re_flags
{
 int cflags; /* Spencer の正規表現コードのコンパイルフラグ */
 bool glob; /* グローバルに実行する(出現ごとに) */
} pg_re_flags;
/*
 * parse_re_flags - regexp_matches などのオプション引数を解析します
 *
 * フラグ --- 出力引数、必要なオプションが記入される
 * opts --- TEXTオブジェクト、またはデフォルトの場合はNULL
 *
 * これは、呼び出し元によって許可されたすべてのオプションを受け入れます。
 * 事後に拒否されてしまう事態を避けたい。
 */
静的ボイド
parse_re_flags(pg_re_flags *フラグ、テキスト *オプション)
{
 /* 正規表現のフレーバーは常にコンパイルフラグに組み込まれます */
 フラグ->cflags = REG_ADVANCED;
 flags->glob = false;

 if (オプション)
 {
 char *opt_p = VARDATA_ANY(opts);
 opt_len = VARSIZE_ANY_EXHDR(opts);
 整数 i;

 (i = 0; i < opt_len; i++) の場合
 {
  スイッチ (opt_p[i])
  {
  ケース 'g':
   フラグ->glob = true;
   壊す;
  case 'b': /* BRE (でもなぜ???) */
   フラグ->cflags &= ~(REG_ADVANCED | REG_EXTENDED | REG_QUOTE);
   壊す;
  case 'c': /* 大文字と小文字を区別します */
   フラグ->cflags &= ~REG_ICASE;
   壊す;
  case 'e': /* プレーンな ERE */
   フラグ->cflags |= REG_EXTENDED;
   フラグ->cflags &= ~(REG_ADVANCED | REG_QUOTE);
   壊す;
  case 'i': /* 大文字と小文字を区別しない */
   フラグ->cflags |= REG_ICASE;
   壊す;
  case 'm': /* n の Perloid 同義語 */
  case 'n': /* \n は ^ $ . [^ */ に影響します
   フラグ->cflags |= REG_NEWLINE;
   壊す;
  case 'p': /* ~Perl, \n は . [^ */ に影響します
   フラグ->cflags |= REG_NLSTOP;
   フラグ->cflags &= ~REG_NLANCH;
   壊す;
  case 'q': /* リテラル文字列 */
   フラグ->cflags |= REG_QUOTE;
   フラグ->cflags &= ~(REG_ADVANCED | REG_EXTENDED);
   壊す;
  case 's': /* 単一行、\n 通常 */
   フラグ->cflags &= ~REG_NEWLINE;
   壊す;
  case 't': /* 厳密な構文 */
   フラグ->cflags &= ~REG_EXPANDED;
   壊す;
  case 'w': /* 奇妙、\n は ^ $ のみに影響します */
   フラグ->cflags &= ~REG_NLSTOP;
   フラグ->cflags |= REG_NLANCH;
   壊す;
  case 'x': /* 拡張構文 */
   フラグ->cflags |= REG_EXPANDED;
   壊す;
  デフォルト:
   ereport(エラー、
    (エラーコード(ERRCODE_INVALID_PARAMETER_VALUE)、
    errmsg("無効な正規表現オプション: \"%c\"",
     opt_p[i])));
   壊す;
  }
 }
 }
}

オプション説明する
b残りの正規表現はBRです
c大文字と小文字を区別するマッチング(演算子タイプをオーバーライド)
e残りの正規表現はERE
大文字と小文字を区別しないマッチング(演算子タイプをオーバーライド)
メートルnの歴史的同義語
改行を感知するマッチング
p部分的な改行を区別する一致
q正規表現を、すべての通常の文字を含むリテラル (「引用符で囲まれた」) 文字列にリセットします。
s改行を区別しないマッチング(デフォルト)
t厳格な文法
改行を区別する(「奇妙な」)一致の一部を反転する
x拡張構文

上記は、PostgreSQL 正規表現のよく使用される関数の詳細な例です。ご質問がある場合は、メッセージを残すか、このサイトのコミュニティで議論してください。お読みいただきありがとうございます。お役に立てれば幸いです。このサイトをサポートしていただきありがとうございます。

以下もご興味があるかもしれません:
  • 解析を実装するためにPostgreSQLデータベースを書き込むSQLスクリプト関数
  • PostgreSQL データベースのウィンドウ関数の構文と使用法
  • PostgreSQL Node.jsでの関数計算メソッドの実装例
  • PostgreSQL におけるシーケンスと関連関数の使用法の詳細な分析
  • Postgresqlカスタム関数の詳細な説明

<<:  JavaScript カラービューア

>>:  FTP環境設定ソリューション(vsftpd)の詳細な説明

推薦する

Windows Server 2016 AD サーバーをセットアップする手順 (画像とテキスト)

導入: AD は Active Directory の略称で、中国語では Active Direct...

Linux/CentOS システムでネットワーク時間を同期する 2 つの方法の詳細な説明

ハードウェア上の理由により、機械は標準時間にある程度追いつけない場合があり、その誤差は 1 か月で数...

formData 形式タイプを使用してファイルをアップロードする Vue の例

Vue では、一般的にフロントエンドとバックエンドを分離したプロジェクトがあり、データ操作を実装する...

MySQL テーブルパーティションの使用法と基本原理の詳細な説明

目次パーティションテーブルとはパーティションテーブルの適用シナリオパーティションテーブルの制限パーテ...

HTMLのリストタグを数える

1. <dl>はリストを定義し、<dt>はリスト内の項目を定義し、<d...

nginx の default_server 定義とマッチングルールの詳細な説明

nginx の default_server ディレクティブは、server_name と一致しない...

vscode で Prettier Code プラグインを使用する詳細なチュートリアル

なぜprettierを使うのですか?大企業では、フロントエンド開発コードに独自のコード標準がある場合...

「いいね!」機能では MySQL と Redis のどちらを使用すればよいでしょうか?

目次1. 初心者が陥りがちな間違い2. Iteratorのremove()メソッドを使用する3. f...

JSはショッピングカート効果の単純な加算と減算を実装します

この記事の例では、ショッピングカートの簡単な追加と削除を実現するためのJSの具体的なコードを参考まで...

Vueデータ変更検出の基本的な実装の簡単な分析

目次1. オブジェクトの変更検出2. オブジェクトに関する質問配列変更検出3.1 背景3.2 実装I...

MySQL 8.0 が起動できない 3534 の解決策

MySQL 8.0 サービスを開始できません最近、 cmdで MySQL サービスを起動するときに遭...

MySQL データをエクスポートおよびインポートするための HeidiSQL ツール

場合によっては、SQL へのデータのエクスポートとインポートを容易にするために、特定のツールを使用し...

MySQL データベースの基本的な SQL ステートメントの概要

この記事では、例を使用して、Mysql データベースの基本的な SQL ステートメントについて説明し...