regex - 在 postgresql 中使用函数修改反向引用

标签 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。

知道为什么会这样吗?

最佳答案

问题:求值顺序

我的猜测(而且只是一个猜测,因为问题不是很清楚)是你对函数调用中参数的求值顺序感到困惑,并试图在 backref 上调用函数 value,但求值顺序意味着它在 正则表达式求值之前对 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,然后将其替换回去。这很 WTFy,为什么?

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

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

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

关于regex - 在 postgresql 中使用函数修改反向引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22887510/

相关文章:

python - 用于附加带有新结果的文件的脚本 - 序列预期错误

用于将 boolean 列排序为 true、null、false 的 SQL

regex - Vim - 将逻辑注入(inject)正则表达式以操作反向引用

python - 正则表达式中的 "\d"是否表示数字?

javascript - 选择javascript正则表达式中的任何符号

sql - 提高 postgreSQL 中简单左连接的性能

postgresql - 无法启动 PostgreSQL

javascript - 如何在函数中使用 javascript 正则表达式反向引用?

Java 正则表达式匹配每 2 个字母之间带有可选多个注释的单词(如何反向引用正则表达式子表达式)

java - Java 中的正则表达式帮助