Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 用二进制字符串替换子字符串_String_Postgresql_Replace_Binary_Postgresql 9.2 - Fatal编程技术网

String 用二进制字符串替换子字符串

String 用二进制字符串替换子字符串,string,postgresql,replace,binary,postgresql-9.2,String,Postgresql,Replace,Binary,Postgresql 9.2,我想对二进制字符串执行子字符串替换操作。有一个函数可以对text()类型的字符串执行此操作: 但不幸的是,bytea()类型的二进制字符串没有 现在我想知道,我是否需要为二进制字符串重新实现此操作,或者我是否可以使用相应的基本字符串函数来完成此任务?是否存在可能破坏我的应用程序的边缘案例: select replace('\000\015Hello World\000\015Hello World'::bytea::text, 'World',

我想对二进制字符串执行子字符串替换操作。有一个函数可以对
text
()类型的字符串执行此操作:

但不幸的是,
bytea
()类型的二进制字符串没有

现在我想知道,我是否需要为二进制字符串重新实现此操作,或者我是否可以使用相应的基本字符串函数来完成此任务?是否存在可能破坏我的应用程序的边缘案例:

select replace('\000\015Hello World\000\015Hello World'::bytea::text,
               'World',
               'Jenny')::bytea

到目前为止,我在文档中找不到具体的注释。有人能帮我一下吗?

转换到
文本
并返回到
bytea
的问题是,如果替换字符串涉及字符串中带引号的字节,它将无法工作。让我们看一个例子

(我正在将
bytea\u output
设置为
hex
以更好地查看文本,否则都是十六进制数)

初始查询:

 with input(x) as (values (('\000\015Hello World\000\015Hello World'::bytea)))
  select replace(x::text, 'World', 'Jenny')::bytea from input;
结果很好:

replace ---------------------------------------- \000\015Hello Jenny\000\015Hello Jenny (1 row) 结果是:

replace ---------------------------------------- IMHello 1orldIMHello 1orld 代替 ---------------------------------------- IMHello 1orldIMHello 1orld 而期望的结果是:
\000\015你好1orld\000\015你好1orld

这是因为中间表示法
\000\015
被替换为
\111\115

转换为
文本并返回到
bytea
的问题是,如果替换字符串涉及字符串中带引号的字节,则无法工作。让我们看一个例子

(我正在将
bytea\u output
设置为
hex
以更好地查看文本,否则都是十六进制数)

初始查询:

 with input(x) as (values (('\000\015Hello World\000\015Hello World'::bytea)))
  select replace(x::text, 'World', 'Jenny')::bytea from input;
结果很好:

replace ---------------------------------------- \000\015Hello Jenny\000\015Hello Jenny (1 row) 结果是:

replace ---------------------------------------- IMHello 1orldIMHello 1orld 代替 ---------------------------------------- IMHello 1orldIMHello 1orld 而期望的结果是:
\000\015你好1orld\000\015你好1orld

这是因为中间表示法
\000\015
被替换为
\111\115
根据@DanielVériteé的建议,我实现了一个
plpgsql
函数,该函数将字符串替换为
bytea
类型的二进制字符串。 在实现中,我只使用了二进制字符串部分的函数,因此我认为应该可以安全使用

这是我的密码:

CREATE OR REPLACE FUNCTION
replace_binary(input_str bytea, pattern bytea, replacement bytea)
RETURNS bytea
AS $$
DECLARE
    buf bytea;
    pos integer;
BEGIN
    buf := '';
    -- validate input
    IF coalesce(length(input_str), 0) = 0 OR coalesce(length(pattern), 0) = 0
    THEN
        RETURN input_str;
    END IF;
    replacement := coalesce(replacement, '');
    LOOP
        -- find position of pattern in input
        pos := position(pattern in input_str);
        IF pos = 0 THEN
            -- not found: append remaining input to buffer and return
            buf := buf || substring(input_str from 1);
            RETURN buf;
        ELSE
            -- found: append substring before pattern to buffer
            buf := buf || substring(input_str from 1 for pos - 1);
            -- append replacement
            buf := buf || replacement;
            -- go on with substring of input
            input_str := substring(input_str from pos + length(pattern));
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql
IMMUTABLE;
至于我的测试用例,它工作得相当好:

with input(buf, pattern, replacement) as (values 
    ('tt'::bytea, 't'::bytea, 'ttt'::bytea),
    ('test'::bytea, 't'::bytea, 'ttt'::bytea),
    ('abcdefg'::bytea, 't'::bytea, 'ttt'::bytea),
    ('\000\015Hello 0orld\000\015Hello 0orld'::bytea, '0'::bytea, '1'::bytea))

select encode(replace_binary(buf, pattern, replacement), 'escape') from input;
预期产出:

               encode               
------------------------------------
 tttttt
 tttesttt
 abcdefg
 \000\rHello 1orld\000\rHello 1orld
(4 rows)

根据@DanielVérité的建议,我实现了一个
plpgsql
函数,该函数用类型为
bytea
的二进制字符串替换字符串。 在实现中,我只使用了二进制字符串部分的函数,因此我认为应该可以安全使用

这是我的密码:

CREATE OR REPLACE FUNCTION
replace_binary(input_str bytea, pattern bytea, replacement bytea)
RETURNS bytea
AS $$
DECLARE
    buf bytea;
    pos integer;
BEGIN
    buf := '';
    -- validate input
    IF coalesce(length(input_str), 0) = 0 OR coalesce(length(pattern), 0) = 0
    THEN
        RETURN input_str;
    END IF;
    replacement := coalesce(replacement, '');
    LOOP
        -- find position of pattern in input
        pos := position(pattern in input_str);
        IF pos = 0 THEN
            -- not found: append remaining input to buffer and return
            buf := buf || substring(input_str from 1);
            RETURN buf;
        ELSE
            -- found: append substring before pattern to buffer
            buf := buf || substring(input_str from 1 for pos - 1);
            -- append replacement
            buf := buf || replacement;
            -- go on with substring of input
            input_str := substring(input_str from pos + length(pattern));
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql
IMMUTABLE;
至于我的测试用例,它工作得相当好:

with input(buf, pattern, replacement) as (values 
    ('tt'::bytea, 't'::bytea, 'ttt'::bytea),
    ('test'::bytea, 't'::bytea, 'ttt'::bytea),
    ('abcdefg'::bytea, 't'::bytea, 'ttt'::bytea),
    ('\000\015Hello 0orld\000\015Hello 0orld'::bytea, '0'::bytea, '1'::bytea))

select encode(replace_binary(buf, pattern, replacement), 'escape') from input;
预期产出:

               encode               
------------------------------------
 tttttt
 tttesttt
 abcdefg
 \000\rHello 1orld\000\rHello 1orld
(4 rows)

你的postgresql版本是什么?您提供的混合9.2和8.0文档页面的链接,以及字符串中反斜杠的解释也取决于版本。@DanielVérité它的版本是9.2。您的postgresql版本是什么?您提供的混合9.2和8.0文档页面的链接,以及字符串中反斜杠的解释也取决于版本。@DanielVéritéit的版本9.2我不知道。我认为
::text
-表示法会将不可打印的字节保留为单个字节,但实际上,
八位字节长度(x)
并不等于
八位字节长度(x::text)
。是否存在/你知道一个变通方法?我看不到一个简单的变通方法。我想我应该在
plpgsql
中迭代执行,而不强制转换为文本,并使用
position
在循环中定位和
overlay
替换。我不知道这一点。我认为
::text
-表示法会将不可打印的字节保留为单个字节,但实际上,
八位字节长度(x)
并不等于
八位字节长度(x::text)
。是否存在/你知道一个变通方法?我看不到一个简单的变通方法。我想我应该在
plpgsql
中迭代执行,而不强制转换为文本,并使用
position
在循环中定位和
overlay
替换。