MaxComputeで特別な意味を持つ文字や直接入力できない文字はエスケープする必要があります。 これにより、文字列を正しく表現して処理できるようになります。 MaxComputeは、文字列内の特殊文字を表すエスケープ文字、または特殊文字に続く文字の解釈を提供します。 このトピックでは、エスケープ文字の使用シナリオについて説明し、MaxComputeでのエスケープ文字の使用方法の例を示します。
シナリオ
プログラミングでは、ほとんどすべての文字列表現にエスケープ文字が使用されます。 エスケープ文字の使用方法は似ています。
'
や"
などの特殊文字の特殊な意味を定義するルールを作成します。特別な意味と目に見えない文字を持つ特殊文字に特別な処理を実行します。 例えば、処理後、特殊文字 'は
\'
にエスケープされ、特殊文字 "は\"
にエスケープされる。ステップ2で得られた結果に対して補足処理を行います。 たとえば、
\\
を使用してバックスラッシュを表します。
ほとんどの仕様では、バックスラッシュ \
をエスケープ文字として使用します。 次のコンテンツでは、バックスラッシュがエスケープ文字として使用される一般的なシナリオについて説明します。
一部の仕様では、バックスラッシュ \
をエスケープ文字として使用しません。 たとえば、URLでは、パーセント記号 %
がエスケープ文字として使用されます。 XMLでは、アンパサンド &
がエスケープ文字として使用されます。
MaxCompute SQL
SQL構文では、文字列の内容は、"abc"
や "123"
などの一重引用符または二重引用符で囲む必要があります。 文字列に1つのタイプの引用符が含まれている場合は、その文字列をもう1つのタイプの引用符で囲むことができます。 例: '二重引用符 (")'
ただし、テキストには一重引用符と二重引用符の両方が含まれる場合があります。 例:
Double quotation mark(")
Single quotation mark(')
上記のコードには、''
と" "
だけでなく、改行も含まれています。 この場合、文字列にほとんど含まれていないバックスラッシュ \
は、1つの文字を表すために次の文字とともに使用されます。 たとえば、\n
は新しい行を表します。 \"
または \'
は、文字列の末尾を示す文字ではなく、文字列の二重引用符または単一引用符を表します。 このように、上記のコードは、'Double quotation mark(")\n Single quotation mark(\')'
または " Double quotation mark(\")\n Single quotation mark(')"
として記述できます。
このように、バックスラッシュには特別な意味があります。 バックスラッシュを含む文字列の場合、バックスラッシュは \\
として記述する必要があります。 この場合、最初のバックスラッシュはエスケープ文字であり、2番目のバックスラッシュは実際の文字です。 次の表に、SQLのエスケープ文字の一般的な構文を示します。
エスケープ文字構文 | 説明 |
\b | 現在の位置を前の列に移動するために使用されるバックスペース。 |
\t | タブ。 |
\n | 現在の位置を次の行の先頭に移動するために使用される新しい行。 |
\r | 現在の位置を現在の行の先頭にリセットするために使用されるキャリッジリターン。 |
\' | 単一の引用符。 |
\" | 二重引用符 (") 。 |
\\ | バックスラッシュ。 |
\; | セミコロン。 |
\Z | Ctrl-Z。 |
\0 または \00 | エンドキャラクター。 |
バックスラッシュの後にエスケープする必要のない文字が続く場合、この文字列はバックスラッシュを含まない文字列と同等です。 たとえば、\a
はa
と同等です。
正規表現
正規表現では、バックスラッシュ \
を使用して非表示の文字を照合します。 正規表現は、テキストの照合に使用されるパターンを宣言します。 ただし、これらのパターンでは、( ) ^ %
などの多数の特殊文字が使用されます。 たとえば、MaxComputeの基になる正規表現エンジンはRE2を使用します。 RE2の詳細については、「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%'; -- The following result is returned: true
特殊文字
文字列
'a\tb'
には3文字が含まれ、文字列内の\t
は1文字と見なされます。select length('a\tb'); -- The following result is returned: 3
文字列
'a\ab'
には3文字が含まれ、\a
はa
として解釈されます。select 'a\ab',length('a\ab'); -- The following result is returned: aab,3
JSON + SQLエスケープ
JSONテキスト {"key":"this is very \" important\"."}
の場合、get_json_object
関数を使用してJSONテキストから値を抽出すると、無効な値が取得されます。
-- Use the new version of the get_json_object function to check the integrity of the JSON text.
set odps.sql.udf.getjsonobj.new=true;
select get_json_object('{"key":"this is very \"important\"."}', '$.key');
-- The following result is returned:
NULL
失敗の理由は、JSONテキストは単一引用符で囲まれていますが、JSONテキストの文字はSQLでエスケープされていないためです。 検証のために次のSELECT
ステートメントを実行します。
select '{"key":"this is very \"important\"."}';
-- The following result is returned:
{"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');
-- The following result is returned:
this is very "important".
単純なテキスト + 正規表現 + SQLエスケープ
関数を使用してテキスト010-12345678
から010
を抽出するには、次の手順を実行します。
正規表現
(\d +)-
を記述します。SQLエスケープルールに基づいて正規表現のバックスラッシュ
\
をエスケープし、正規表現を単一引用符で囲み、文字列'(\\d +)-'
を取得します。
検証のためにMaxComputeで次のステートメントを実行します。
select REGEXP_EXTRACT('010-12345678', '(\\d+)-');
-- The following result is returned:
010
JSON + 正規表現 + SQLエスケープ
正規表現を使用して、JSON文字列 {"key":"this is very \" important\"."}
などのエスケープ文字を含む文字列からimportant
を一致させるには、次の手順を実行します。
正規表現
\"(.*)\"
を記述します。正規表現でバックスラッシュをエスケープします。 エスケープ後、正規表現は
\\"(.*)\\"
に変更されます。\
を\\
に置き換えて、式のSQLエスケープを実行します。 簡単にするために、式を単一引用符で囲み、'\\\\ "(.*)\\\\"'
という文字列を取得します。
検証のためにMaxComputeで次のステートメントを実行します。
select REGEXP_EXTRACT('{"key":"this is very \\"important\\"."}', '\\\\"(.*)\\\\"');
-- The following result is returned:
important
結果は予想通りです。 同様のシナリオでは、ロジックを明確にするために、まずJSONテキストを解析することをお勧めします。 サンプル文:
set odps.sql.udf.getjsonobj.new=true;
select REGEXP_EXTRACT(get_json_object('{"key":"this is very \\"important\\"."}', '$.key'), '"(.*)"');
-- The following result is returned:
important
上記の例では、ビジネス要件を満たす有効なステートメントが記述されています。 ただし、エスケープ操作後の文字列 '\\\\\ "(.*)\\\\"'
はわかりにくい。 SELECT
ステートメントを使用して、生の文字列に対して逆の操作を実行し、生の文字列と正規表現ツールに基づいて照合するパターンを推測できます。 サンプルSELECTステートメント:
select '\\\\"(.*)\\\\"';
-- The following result is returned:
\\"(.*)\\"
SQLエスケープ機能強化
バックスラッシュ \
は、SQL、JSON、および正規表現ではエスケープ文字として使用されます。これは、バックスラッシュ
は一般的なステートメントではめったに使用されないためです。 ただし、SQL、JSON、および正規表現の仕様を一緒に使用すると、バックスラッシュが頻繁に表示される場合があります。 これにより、エスケープ文字が膨らみます。 この問題に対処するために、MaxComputeは新しいエスケープメソッドR "()"
を導入しました。 エスケープメソッドを使用する場合、括弧 () で囲まれた文字は、バックスラッシュ \
を使用してエスケープする必要はありません。
例:
R "(abc)"
は'abc'
に相当する。R'(\\"(.*)\\")'
は、' \\\\\ "(.*) \\\\\" '
と同等です。
文字R
は生の文字列を示し、大文字と小文字は区別されません。 r
に変更できます。 二重引用符を一重引用符に変更することもできます。 MaxComputeでは、エスケープする各文字列に \
を追加する必要はありません。 文字列の両側を変更するだけで済みます。 次のステートメントを実行して、正規表現を使用してJSON文字列から重要
に一致させることもできます。
select REGEXP_EXTRACT(R'({"key":"this is very \"important\"."})', R'(\\"(.*)\\")');
-- The following result is returned:
important
このメソッドは、JSON文字列と正規表現のエスケープを大幅に簡素化します。