将字符串中的所有十六进制转换为其在 Redshift 中的 char 值
Convert all hex in a string to its char value in Redshift
在 Redshift 中,我尝试像这样转换字符串:
http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob
看起来像这样:
http://www.amazon.com/Test?name=Gary&Bob
基本上我需要将字符串中的所有十六进制转换为它的字符值。我能想到的唯一方法是使用正则表达式函数。我尝试以两种不同的方式进行操作,但都收到了错误消息:
SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', CHR(x'\1'::int))
ERROR: 22P02: "\" is not a valid hexadecimal digit
SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])',CHR(STRTOL('0x'||'\1', 16)::int))
ERROR: 22023: The input 0x is not valid to be converted to base 16
CHR 和 STRTOL 函数自行运行。例如:
SELECT CHR(x'3A'::int)
SELECT CHR(STRTOL('0x3A', 16)::int)
两个returns
:
如果我 运行 使用不同的函数(CHR 和 STRTOL 除外)相同的模式,它会起作用:
REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', LOWER('{H}'||'\1'||'{/H}'))
returns
http{h}3A{/h}{h}2F{/h}{h}2F{/h}www.amazon.com{h}2F{/h}Test{h}3F{/h}name{h}3D{/h}Gary{h}26{/h}Bob
但由于某些原因,这些函数无法识别正则表达式匹配组。
关于如何执行此操作的任何提示?
我想另一个解决方案是对所有特殊的十六进制字符使用嵌套的 REPLACE() 函数,但这可能是最后的手段。
你想做的事情叫做"URL decode"。
目前没有内置函数可以执行此操作,但您可以创建一个自定义函数 User-Defined Function (make sure you have the required privileges):
CREATE FUNCTION urldecode(url VARCHAR)
RETURNS varchar
IMMUTABLE AS $$
import urllib
return urllib.unquote(url).decode('utf8') # or 'latin-1', depending on how the text is encoded
$$ LANGUAGE plpythonu;
示例查询:
SELECT urldecode('http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob');
结果:
http://www.amazon.com/Test?name=Gary&Bob
我在 REDSHIFT 中尝试了@hiddenbit 的回答,但 Python 3 不受支持。然而,以下 Py2 代码确实对我有用:
DROP FUNCTION urldecode(varchar);
CREATE FUNCTION urldecode(url VARCHAR)
RETURNS varchar
IMMUTABLE AS $$
import urllib
return urllib.unquote(url)
$$ LANGUAGE plpythonu;
在 Redshift 中,我尝试像这样转换字符串:
http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob
看起来像这样:
http://www.amazon.com/Test?name=Gary&Bob
基本上我需要将字符串中的所有十六进制转换为它的字符值。我能想到的唯一方法是使用正则表达式函数。我尝试以两种不同的方式进行操作,但都收到了错误消息:
SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', CHR(x'\1'::int))
ERROR: 22P02: "\" is not a valid hexadecimal digit
SELECT REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])',CHR(STRTOL('0x'||'\1', 16)::int))
ERROR: 22023: The input 0x is not valid to be converted to base 16
CHR 和 STRTOL 函数自行运行。例如:
SELECT CHR(x'3A'::int)
SELECT CHR(STRTOL('0x3A', 16)::int)
两个returns
:
如果我 运行 使用不同的函数(CHR 和 STRTOL 除外)相同的模式,它会起作用:
REGEXP_REPLACE(hex_string, '%([[:xdigit:]][[:xdigit:]])', LOWER('{H}'||'\1'||'{/H}'))
returns
http{h}3A{/h}{h}2F{/h}{h}2F{/h}www.amazon.com{h}2F{/h}Test{h}3F{/h}name{h}3D{/h}Gary{h}26{/h}Bob
但由于某些原因,这些函数无法识别正则表达式匹配组。
关于如何执行此操作的任何提示?
我想另一个解决方案是对所有特殊的十六进制字符使用嵌套的 REPLACE() 函数,但这可能是最后的手段。
你想做的事情叫做"URL decode"。
目前没有内置函数可以执行此操作,但您可以创建一个自定义函数 User-Defined Function (make sure you have the required privileges):
CREATE FUNCTION urldecode(url VARCHAR)
RETURNS varchar
IMMUTABLE AS $$
import urllib
return urllib.unquote(url).decode('utf8') # or 'latin-1', depending on how the text is encoded
$$ LANGUAGE plpythonu;
示例查询:
SELECT urldecode('http%3A%2F%2Fwww.amazon.com%2FTest%3Fname%3DGary%26Bob');
结果:
http://www.amazon.com/Test?name=Gary&Bob
我在 REDSHIFT 中尝试了@hiddenbit 的回答,但 Python 3 不受支持。然而,以下 Py2 代码确实对我有用:
DROP FUNCTION urldecode(varchar);
CREATE FUNCTION urldecode(url VARCHAR)
RETURNS varchar
IMMUTABLE AS $$
import urllib
return urllib.unquote(url)
$$ LANGUAGE plpythonu;