使用转义换行符和回车符对字符串进行转义
Posted
技术标签:
【中文标题】使用转义换行符和回车符对字符串进行转义【英文标题】:Unescape a string with escaped newlines and carriage returns 【发布时间】:2016-01-19 02:36:46 【问题描述】:我正在尝试编写一个混淆/审查/编辑文本的 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 转义序列。
【问题讨论】:
【参考方案1】:要“取消转义”字符串,您必须“执行”它 - 字面意思。使用EXECUTE
command in plpgsql。
您可以将其包装成一个函数。幼稚的做法:
CREATE OR REPLACE FUNCTION f_unescape(text, OUT _t text)
LANGUAGE plpgsql STABLE AS
$func$
BEGIN
EXECUTE 'SELECT E''' || $1 || ''''
INTO _t;
END
$func$;
呼叫:
SELECT f_unescape('\r\nabcdef\t0123\x123\n');
这个简单的函数容易受到原始字符串中的单引号的影响,需要对其进行转义。但这有点棘手。在 Posix 转义字符串语法中,单引号可以通过两种方式转义:\'
或 ''
。但我们也可以有\\'
等。基础知识:
我们可以将字符串括在美元引号中,但这不适用于 Posix 转义字符串语法。 E'\''
不能替换为 。我们可以将E$$\'$$
SET standard_conforming_strings = off
添加到函数中,然后我们就不必在字符串前面加上E
。但这会禁用函数内联,并且 interpret 在函数体的任何地方都会转义。
相反,转义所有'
和所有(可选)前导\
与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
LANGUAGE plpgsql STABLE AS
$func$
BEGIN
EXECUTE $$SELECT E'$$ || regexp_replace($1, '(\\*)(\''+)', '\1\1\2\2', 'g') || $$'$$
INTO _t;
END
$func$;
操作无法逆转可靠。没有办法知道哪个特殊字符之前被转义了,哪个没有。您可以全部逃避,也可以不逃避。或者像以前一样手动进行。但如果文字和转义形式中包含相同的字符,则无法再区分它们。
测试用例:
SELECT t, f_unescape(t)
FROM (
VALUES
($$'$$)
, ($$''$$)
, ($$'''$$)
, ($$\'$$)
, ($$\\'$$)
, ($$\\\'$$)
, ($$\\\'''$$)
, ($$\r\\'nabcdef\\\t0123\x123\\\\\'''\n$$)
) v(t);
【讨论】:
以上是关于使用转义换行符和回车符对字符串进行转义的主要内容,如果未能解决你的问题,请参考以下文章