MaxCompute では、特別な意味を持つ文字や直接入力できない文字はエスケープする必要があります。 これにより、文字列を正確に表現および処理できます。 このトピックでは、エスケープ文字の使用シナリオについて説明し、MaxCompute でのエスケープ文字の使用方法の例を示します。
シナリオ
プログラミングでは、エスケープ文字はほぼすべての文字列表現で使用されます。 エスケープ文字の使用方法も同様です。
'や"などの特殊文字に特別な意味を定義するルールを作成します。特別な意味を持つ特殊文字と不可視文字に対して特別な処理を実行します。 たとえば、処理後、特殊文字 ' は
\'にエスケープされ、特殊文字 " は\"にエスケープされます。ステップ 2 で得られた結果に対して補足処理を実行します。 たとえば、
\\を使用してバックスラッシュを表します。
ほとんどの仕様では、バックスラッシュ \ をエスケープ文字として使用します。 次の内容では、バックスラッシュがエスケープ文字として使用される典型的なシナリオについて説明します。
一部の仕様では、バックスラッシュ \ をエスケープ文字として使用していません。 たとえば、URL では、パーセント記号 % がエスケープ文字として使用されます。 XML では、アンパサンド & がエスケープ文字として使用されます。
MaxCompute SQL
SQL 構文では、文字列の内容は "abc" や '123' など、一重引用符または二重引用符で囲む必要があります。 文字列に一種類の引用符が含まれている場合は、文字列をもう一方の種類の引用符で囲むことができます。 例: '二重引用符 (")'。 ただし、テキストには一重引用符と二重引用符の両方が含まれている場合があります。 例:
Double quotation mark(")
Single quotation mark(')上記のコードには、'' と "" だけでなく、改行も含まれています。 この場合、文字列にほとんど含まれていないバックスラッシュ \ を次の文字とともに使用して、1 つの文字を表します。 たとえば、\n は改行を表します。 \" または \' は、文字列の終わりを示す文字ではなく、文字列内の二重引用符または一重引用符を表します。 このようにして、上記のコードは 'Double quotation mark(")\nSingle quotation mark(\')' または "Double quotation mark(\")\nSingle quotation mark(')" と書くことができます。
このように、バックスラッシュには特別な意味があります。 バックスラッシュを含む文字列の場合、バックスラッシュは \\ と記述する必要があります。 この場合、最初のバックスラッシュはエスケープ文字であり、2 番目のバックスラッシュは実際の文字です。 次の表に、SQL でのエスケープ文字の一般的な構文を示します。
エスケープ文字の構文 | 説明 |
\b | 現在の位置を前の列に移動するために使用されるバックスペース。 |
\t | タブ。 |
\n | 現在の位置を次の行の先頭に移動するために使用される改行。 |
\r | 現在の位置を現在の行の先頭にリセットするために使用されるキャリッジリターン。 |
\' | 一重引用符。 |
\" | 二重引用符 (")。 |
\\ | バックスラッシュ。 |
\; | セミコロン。 |
\Z | Ctrl-Z。 |
\0 or \00 | 終了文字。 |
バックスラッシュの後にエスケープする必要のない文字が続く場合、この文字列はバックスラッシュを含まない文字列と同じです。 たとえば、\a は a と同じです。
正規表現
正規表現では、バックスラッシュ \ は不可視文字と一致するために使用されます。 正規表現は、テキストと一致するために使用されるパターンを宣言します。 ただし、これらのパターンでは、( ) ^ % などの多数の特殊文字が使用されます。 たとえば、MaxCompute の基盤となる正規表現エンジンは RE2 を使用します。 次の表に、バックスラッシュ \ がエスケープ文字として使用される構文を示します。
エスケープ文字の構文 | 説明 |
\d | 数字と一致します。 これは |
\D | 数字以外の文字と一致します。 これは |
\s | 空白文字と一致します。 これは |
\S | 空白以外の文字と一致します。 これは |
\w | 英数字と一致します。 これは |
\W | 英数字以外の文字と一致します。 これは |
完全な正規表現構文は複雑です。 regexr または regex101 オンラインツールを使用して、期待どおりの正規表現を作成できます。
JSON
JSON は、データの送信によく使用されるシンプルなテキストプロトコルです。 JSON の詳細については、「JSON」をご参照ください。 次の表に、JSON でのエスケープ文字の構文を示します。 JSON では、バックスラッシュ \ がエスケープ文字として使用されます。
エスケープ文字の構文 | 説明 |
\" | 二重引用符。 |
\\ | バックスラッシュ。 |
\/ | スラッシュ。 |
\b | バックスペース。 |
\f | フォームフィード。 |
\n | 改行。 |
\r | キャリッジリターン。 |
\t | 水平タブ。 |
\u+4 桁の 16 進数値 | Unicode 文字。 |
JSON のエスケープ文字の設計は SQL のエスケープ文字の設計と似ています。 JSON オンラインツール JSONLint を使用して、テキストが JSON 仕様に準拠しているかどうかを確認できます。
例
バックスラッシュ \ は、多くの仕様でエスケープ文字として使用されます。 バックスラッシュが他の文字と組み合わせてエスケープに使用されている場合、テキストを理解することは困難です。 この場合、テキストのネスト構造を理解し、上記のオンラインツールを使用して文字を段階的にエスケープおよびエスケープ解除して、有効な構文の文を作成する必要があります。 次の内容では、例について説明します。
エスケープ文字を使用して、エスケープ文字の次の文字を解釈する
MaxCompute SQL では、一重引用符または二重引用符を使用して文字列定数を表すことができます。 一重引用符で囲まれた文字列に二重引用符を含めることも、二重引用符で囲まれた文字列に一重引用符を含めることもできます。 それ以外の場合は、エスケープ文字を使用する必要があります。 例:
"I'm a happy manong." 'I\'m a happy manong.'LIKE を使用して
%または_と一致させる場合は、特殊文字をエスケープする必要があります。 ステートメントの例:select 'ab_cde' like 'ab\_c%'; -- 返される結果: true
特殊文字
文字列
'a\tb'には 3 文字が含まれており、文字列内の\tは 1 文字と見なされます。select length('a\tb'); -- 返される結果: 3文字列
'a\ab'には 3 文字が含まれており、\aはaとして解釈されます。select 'a\ab',length('a\ab'); -- 返される結果: aab,3
JSON + SQL エスケープ
JSON テキスト {"key":"this is very \"important\"."} の場合、get_json_object 関数を使用して JSON テキストから値を抽出すると、無効な値が取得されます。
-- 新バージョンの get_json_object 関数を使用して、JSON テキストの整合性を確認します。
set odps.sql.udf.getjsonobj.new=true;
select get_json_object('{"key":"this is very \"important\"."}', '$.key');
-- 返される結果:
NULL失敗の理由は、JSON テキストが一重引用符で囲まれているにもかかわらず、JSON テキストの文字が SQL でエスケープされていないためです。 確認のために次の SELECT ステートメントを実行します。
select '{"key":"this is very \"important\"."}';
-- 返される結果:
{"key":"this is very "important"."}JSON テキストのバックスラッシュが消えています。 これは、コンパイラが解析中に JSON エスケープ文字を SQL エスケープ文字と見なし、\" を " として解釈するためです。 取得された結果は JSON 構文に準拠していません。 これにより、解析エラーが発生します。 有効な SQL エスケープ文字を JSON テキストに追加します。 JSON テキストは '{"key":"this is very \\"important\\"."}' に変更されます。 次に、get_json_object 関数を使用して値を再度抽出します。 返される結果は有効です。
set odps.sql.udf.getjsonobj.new=true;
select get_json_object('{"key":"this is very \\"important\\"."}', '$.key');
-- 返される結果:
this is very "important".シンプルなテキスト + 正規表現 + SQL エスケープ
関数を使用してテキスト 010-12345678 から 010 を抽出するには、次の手順を実行します。
正規表現
(\d+)-を記述します。SQL エスケープルールに基づいて正規表現のバックスラッシュ
\をエスケープし、正規表現を一重引用符で囲んで文字列'(\\d+)-'を取得します。
確認のために MaxCompute で次のステートメントを実行します。
select REGEXP_EXTRACT('010-12345678', '(\\d+)-');
-- 返される結果:
010JSON + 正規表現 + SQL エスケープ
JSON 文字列 {"key":"this is very \"important\"."} など、エスケープ文字を含む文字列から正規表現を使用して important と一致させるには、次の手順を実行します。
正規表現
\"(.*)\"を記述します。正規表現のバックスラッシュをエスケープします。 エスケープ後、正規表現は
\\"(.*)\\"に変更されます。\を\\に置き換えることによって、式に対して SQL エスケープを実行します。 簡単にするために、式を一重引用符で囲んで文字列'\\\\"(.*)\\\\"'を取得します。
確認のために MaxCompute で次のステートメントを実行します。
select REGEXP_EXTRACT('{"key":"this is very \\"important\\"."}', '\\\\"(.*)\\\\"');
-- 返される結果:
important結果は期待どおりです。 同様のシナリオでは、最初に JSON テキストを解析してロジックを明確にすることをお勧めします。 ステートメントの例:
set odps.sql.udf.getjsonobj.new=true;
select REGEXP_EXTRACT(get_json_object('{"key":"this is very \\"important\\"."}', '$.key'), '"(.*)"');
-- 返される結果:
important前の例では、ビジネス要件を満たす有効なステートメントが記述されています。 ただし、エスケープ操作の後、文字列 '\\\\"(.*)\\\\"' は理解しにくくなります。 SELECT ステートメントを使用して生の文字列に対して逆の操作を実行し、生の文字列と正規表現ツールに基づいて一致させたいパターンを推測できます。 SELECT ステートメントの例:
select '\\\\"(.*)\\\\"';
-- 返される結果:
\\"(.*)\\"SQL エスケープの強化
バックスラッシュは一般的なステートメントではめったに使用されないため、SQL、JSON、および正規表現ではバックスラッシュ \ がエスケープ文字として使用されます。 ただし、SQL、JSON、および正規表現の仕様を一緒に使用すると、バックスラッシュが頻繁に表示される場合があります。 これにより、エスケープ文字が肥大化します。 この問題に対処するために、MaxCompute は新しいエスケープ方法 R"()" を導入しました。 このエスケープ方法を使用すると、かっこ () で囲まれた文字をバックスラッシュ \ でエスケープする必要はありません。
例:
R"(abc)"は'abc'と同じです。R'(\\"(.*)\\")'は'\\\\"(.*)\\\\"'と同じです。
文字 R は生の文字列を示し、大文字と小文字は区別されません。 r に変更できます。 二重引用符を一重引用符に変更することもできます。 MaxCompute では、エスケープする各文字列に \ を追加する必要はありません。 文字列の両側を変更するだけで済みます。 また、次のステートメントを実行して、正規表現を使用して JSON 文字列から important と一致させることもできます。
select REGEXP_EXTRACT(R'({"key":"this is very \"important\"."})', R'(\\"(.*)\\")');
-- 返される結果:
importantこの方法により、JSON 文字列と正規表現のエスケープが大幅に簡素化されます。