自用MySQL5.7中的正则表达式替换函数regxp_replace_all

注意!

本函数为自用函数,效率不高,还有BUG,请别盲目使用或修改后再使用。

已知的坑

好几个参数都是LONGTEXT。若设置为varchar,在比较新的Navicat版本中,传入超长的字符串并不会报错。但结果是错的,我怀疑Navicat会“帮你”将超长的文本截取至定义的varchar范围内。
所以在修改本函数之前,请确认需要处理的数据的长度。

MySQL函数

#创建前删除已经创建的自定义函数
DROP FUNCTION IF EXISTS regexp_replace_all;
#创建 regexp_replace函数
DELIMITER $$  
CREATE FUNCTION `regexp_replace_all`(ori_str LONGTEXT,pattern VARCHAR(1000),repl_str VARCHAR(1000))  
	RETURNS LONGTEXT
	DETERMINISTIC  
BEGIN  
	DECLARE tmp_str LONGTEXT;  
	DECLARE target_str LONGTEXT;  
	DECLARE str0 LONGTEXT;  
	DECLARE i1 INT;
	DECLARE i2 INT;
 
	# 此处假设MySQL5.7的正则表达式匹配类型是非贪婪模式,目前没有在官方文档内确认。
	# 本函数的基本逻辑是,先从原文本开头不断的裁剪,不能匹配上时,则证明找到了目标文本的开头;如法炮制,找到目标文本的结尾。以此确定目标文本的位置。
	# 示例:若原文本是AABBCC,正则表达式为B+,大致流程如下
	# i1=1, tmp_str="AABBCC", match
	# i1=2, tmp_str="ABBCC", match
	# i1=3, tmp_str="BBCC", match
	# i1=4, tmp_str="BCC", match
	# i1=5, tmp_str="CC", unmatch
	# 定位开始位置为4
	# i2=6, tmp_str="BCC", match
	# i2=5, tmp_str="BC", match
	# i2=4, tmp_str="B", match
	# i2=4, tmp_str="", unmatch
	# 定位结束位置为4
	# 所以输出结果是replace("AABBCC", "B", "")

	# Warning:此函数效率比较差,而且在重复replace的时候,会重复匹配相同的位置,有违正则表达式的匹配逻辑。
	# Warning:此函数在pattern能匹配repl_str会进入死循环,优化后再考虑加入报错机制。
	# Warning:函数返回的是长文本格式,在存入数据库之前考虑转换一下数据类型。

	SET tmp_str = ori_str; # 强迫症行为

	# 循环查找以替换所有的目标字符串
	loop0: LOOP
		IF NOT tmp_str REGEXP pattern THEN  
			LEAVE loop0;  
		END IF;
		
		# 目前初始值多设了一位
		SET i1 = 1;
		SET i2 = CHAR_LENGTH(tmp_str);
		
		# 循环从头裁剪字符串
		loop1: LOOP
			SET str0 = SUBSTR(tmp_str, i1, i2-i1+1);
			IF NOT str0 REGEXP pattern THEN
				SET i1 = i1-1; # 当不能匹配上时,还原至上次循环到的位置。
				LEAVE loop1;
			ELSE
				SET i1 = i1+1;
			END IF;
		END LOOP;
		
		# 循环从尾裁剪字符串
		loop2: LOOP
			SET str0 = SUBSTR(tmp_str, i1, i2-i1+1);
			IF NOT str0 REGEXP pattern THEN
				SET i2 = i2+1; # 当不能匹配上时,还原至上次循环到的位置。
				LEAVE loop2;
			ELSE
				SET i2 = i2-1;  
			END IF;
		END LOOP;
		
		# 根据定位到的头和尾,截取目标文本
		SET target_str = SUBSTR(tmp_str, i1, i2-i1+1);
		
		# 替换原文本中的目标文本
		SET tmp_str = REPLACE(tmp_str, target_str, repl_str);
	END LOOP;  

	RETURN tmp_str;
END$$  
DELIMITER ;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值