使用postgresql中的函数修改反向引用

时间:2014-04-05 22:10:53

标签: regex postgresql backreference

我想将(int)值添加到反向引用中。

为此我创建了一个函数并传递了适当的反向引用。如果在没有任何修改的情况下返回的反向引用工作正常,但是当我尝试修改或使用传递的反向引用上的任何其他函数时,它假定\ 3作为参数值而不是反向引用值本身。

例如 -

CREATE OR REPLACE FUNCTION add10(text) returns text as $$
DECLARE
    t int;
BEGIN   
    t := to_number($1, '999999') + 10;
    return trim(to_char(t, '999999'), ' ');
END;
$$ LANGUAGE plpgsql;

然后:

select regexp_replace('890808', '80(\d+)', add10('\1'), 'g');

应该给出结果

 test
-------
 89018
(1 row)

然而它给出了 -

 test
-------
 89011
(1 row)

将$ 1的值作为1(反向引用号)而不是值8。

为什么会发生这种情况?

1 个答案:

答案 0 :(得分:1)

问题:评估顺序

我的猜测(只是猜测,因为问题不是很清楚)是你对函数调用中参数的评估顺序感到困惑,并试图调用一个函数backref ,但评估顺序意味着它在 regexp评估之前在backref字符串上调用。

假设add10t是相同的,那么:

select regexp_replace('890808', '80(\d+)', add10('\1'), 'g');

通过首先调用add10('\1')进行评估。那将反过来运行:

select to_number('\1', '999999') + 10 into t;

由于select to_number('\1', '999999')产生的值为1,因此您11会获得t。然后你将它转换回一个字符串(通过一种相当奇怪的方法,为什么你没有把它转换成它)。

因此,您已将'\1'替换为'11',因此您的regexp_replace电话似乎如下:

select regexp_replace('890808', '80(\d+)', '11`, 'g');

...您可以从中看到意外结果的来源。

解决方案:拆分值,修改它,然后重新组装

我认为你想要的结果没有任何意义,所以我无法弄清楚如何制作它。你似乎试图在" 80"之前保留所有数字,丢弃" 80",转换" 80"之后的所有数字。一个数字并加上10,然后将其替换回来。这很漂亮,为什么?

正则表达式是分割数字的一种方法,但最好的方法通常是模数和余数:

craig=> SELECT 890808 / 10000, 890808 % 10000;
 ?column? | ?column? 
----------+----------
       89 |      808
(1 row)

如果您必须使用正则表达式(例如,如果它是混合的字母数字或者您的条件不容易用地方值表示),您可能想要使用regexp_split_to_array