我正在尝试编写一个混淆/审查/编辑文本的PLPGSQL函数。
-- Obfuscate a body of text by replacing lowercase letters and numbers with # symbols.
CREATE OR REPLACE FUNCTION obfuscate(str text) RETURNS text AS $$
BEGIN
str := replace(str, '\r', E'\r');
str := replace(str, '\n', E'\n');
str := translate(str, 'abcdefghijklmnopqrstuvwxyz0123456789', rpad('#',36,'#'));
str := replace(str, E'\r', '\r');
str := replace(str, E'\n', '\n');
RETURN str;
END
$$ LANGUAGE plpgsql;
这样可行,但请注意舞蹈将转义的换行符和回车符转换为各自的字节,然后再返回。这是因为我的数据集包含已被转义的字符串(已被序列化为JSON / YAML的数据),我不想破坏这些值。
还有另一种更方便的方法来取消字符串吗?处理其他转义值也很棒,比如unicode转义序列。
答案 0 :(得分:2)
To" unescape"一个字符串,你必须"执行"它 - 字面意思。使用EXECUTE
command in plpgsql。
您可以将其包装成一个函数。天真的方法:
CREATE OR REPLACE FUNCTION f_unescape(text, OUT _t text) AS
$func$
BEGIN
EXECUTE 'SELECT E''' || $1 || ''''
INTO _t;
END
$func$ LANGUAGE plpgsql STABLE;
呼叫:
SELECT f_unescape('\r\nabcdef\t0123\x123\n');
这种天真的形式容易受到原始字符串中的单引号的影响,需要对其进行转义。但这有点棘手。单引号可以使用posix转义字符串语法以两种方式转义:\'
或''
。但我们也可能有\\'
等基础知识:
我们可以将字符串括在美元引用中,但这不适用于posix转义字符串语法。 E'\''
无法替换为 。我们可以在函数中添加E$$\'$$
SET standard_conforming_strings = off
,然后我们就不必在E
前添加字符串了。但这会禁用函数体内的函数内联和解释转义。
相反,使用'
转义所有\
和所有(可选)前导regexp_replace()
:
regexp_replace($1, '(\\*)(\''+)', '\1\1\2\2', 'g')
(\\*)
.. 0或更多领先\
(\''+)
..捕获1个或多个'
'\1\1\2\2'
..每场比赛加倍
'g'
..替换所有匹配项,而不仅仅是第一个
CREATE OR REPLACE FUNCTION f_unescape(IN text, OUT _t text)
RETURNS text AS
$BODY$
BEGIN
EXECUTE $$SELECT E'$$ || regexp_replace($1, '(\\*)(\''+)', '\1\1\2\2', 'g') || $$'$$
INTO _t;
END
$BODY$
LANGUAGE plpgsql STABLE;
我假设你知道操作无法逆转可靠。没有办法告诉哪个特殊字符之前已被转义,哪个不是。你可以逃脱全部或全部。或者像以前一样手动完成。但如果文字和转义形式中包含相同的字符,则不能再将它们分开。
测试用例:
SELECT t, f_unescape(t)
FROM (
VALUES
($$'$$)
, ($$''$$)
, ($$'''$$)
, ($$\'$$)
, ($$\\'$$)
, ($$\\\'$$)
, ($$\\\'''$$)
, ($$\r\\'nabcdef\\\t0123\x123\\\\\'''\n$$)
) v(t);