根据值将字符串替换为列表中的另一个字符串

Replace a string with another string from a list depending on the value

假设我有这个字符串:'2015/4/21 (Tuesday)'。我想用另一个字符串替换 'Tuesday',例如:'cat'。结果应该是:'2015/4/21 (cat)'.

但我也希望它是动态的,如果它是 'Tuesday',那么 'cat'。如果是'Monday',那就是狗等

如何在 PostgreSQL 8.4 中执行此操作?

有一个类似的post:postgresql - replace all instances of a string within text field

但我的需要根据日期替换某些东西 动态 并且 post 替换已知值。

您应该可以使用嵌套 replace():

select replace(replace(str, 'Tuesday', 'cat'), 'Monday', 'dog')

如果该值不在字符串中,则不会发生任何事情。

对于几个互斥替换,嵌套替换语句是最简单和最快的方法。就 .

但是对于多个替代品来说,这并不能很好地扩展,并且存在 陷阱 :

子字符串

当字符串可以互为子串时,就变得不明确了。考虑这两个表达式:

SELECT replace((replace('2015 (Monday)', 'day', 'snake'), 'Monday', 'dog')
     , replace((replace('2015 (Monday)', 'Monday', 'dog'), 'day', 'snake');

结果取决于替换顺序。你必须定义优先级。通常您会先替换较长的字符串。

连锁店

那么也有可能一个替换可能为下一个创建匹配:

SELECT replace((replace('2015 (Sunday)', 'Sun', 'Mon'), 'Monday', 'dog')
     , replace((replace('2015 (Sunday)', 'Monday', 'dog'), 'Sun', 'Mon');

同样,您必须定义优先级。
每个替换都可能影响下一个。如果更换了几个以上,这就会变得模糊并且很快容易出错。如果更换可以更改,也很难维护。

正如我所说,只有星期几,嵌套 replace() 语句就可以了。这实际上不是“动态的”。如果工作日只是为了说明问题,而您实际上必须处理更多情况或真正的动态字符串,我会考虑一种不同的方法。在此相关答案中找到完整的动态解决方案

另一个选项是递归函数:

CREATE OR REPLACE FUNCTION replace_recursive(search text, from_to text[][])
RETURNS TEXT LANGUAGE plpgsql AS $$
BEGIN
    IF (array_length(from_to,1) > 1) THEN
        RETURN replace_recursive(
            replace(search, from_to[1][1], from_to[1][2]),
            from_to[2:array_upper(from_to,1)]
        );
    ELSE
        RETURN replace(search, from_to[1][1], from_to[1][2]);
    END IF;
END;$$;

结果:

select replace_recursive('from1, from2, from3', array[['from1', 'to1'], ['from2', 'to2']]);

┌───────────────────┐
│ replace_recursive │
├───────────────────┤
│ to1, to2, from3   │
└───────────────────┘