Pis*_*3.0 482 regex mysql mysql-udf
我有一张约500k行的桌子; varchar(255)UTF8列filename包含文件名;
我试图从文件名中删除各种奇怪的字符 - 我以为我会使用一个字符类: [^a-zA-Z0-9()_ .\-]
现在,MySQL中是否有一个函数可以让你通过正则表达式替换?我正在寻找与REPLACE()函数类似的功能 - 简化示例如下:
SELECT REPLACE('stackowerflow', 'ower', 'over');
Output: "stackoverflow"
/* does something like this exist? */
SELECT X_REG_REPLACE('Stackoverflow','/[A-Zf]/','-');
Output: "-tackover-low"
Run Code Online (Sandbox Code Playgroud)
我知道REGEXP/RLIKE,但那些只检查是否有匹配,没有什么比赛是.
(我可以SELECT pkey_id,filename FROM foo WHERE filename RLIKE '[^a-zA-Z0-9()_ .\-]'从PHP脚本做一个" ",做一个preg_replace然后" UPDATE foo ... WHERE pkey_id=...",但这看起来像一个最后的缓慢和丑陋的黑客)
Jer*_*ein 141
没有.
但是,如果您可以访问您的服务器,则可以使用用户定义的函数(UDF),如mysql-udf-regexp.
编辑: MySQL 8.0+你可以原生使用REGEXP_REPLACE.更多回答如上
Ben*_*rth 123
请改用MariaDB.它有一个功能
REGEXP_REPLACE(col, regexp, replace)
Run Code Online (Sandbox Code Playgroud)
请注意,您也可以使用正则表达式分组(我发现它非常有用):
SELECT REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '\\2 - \\1 - \\3')
Run Code Online (Sandbox Code Playgroud)
回报
over - stack - flow
Run Code Online (Sandbox Code Playgroud)
Rya*_*ard 108
我的强力方法让这个工作只是:
mysqldump -u user -p database table > dump.sqlfind /path/to/dump.sql -type f -exec sed -i 's/old_string/new_string/g' {} \;显然,您可以在文件上执行其他perl regeular表达式.mysqlimport -u user -p database table < dump.sql如果要确保字符串不在数据集中的其他位置,请运行一些正则表达式以确保它们都出现在类似的环境中.在运行替换之前创建备份并不困难,以防您意外破坏丢失信息深度的内容.
Luk*_*zda 53
MySQL 8.0+你可以原生使用REGEXP_REPLACE.
REGEXP_REPLACE(expr,pat,repl [,pos [,occurrence [,match_type]]])
将字符串expr中与模式pat指定的正则表达式匹配的匹配项替换为替换字符串repl,并返回结果字符串.如果expr,pat或repl为NULL,则返回值为NULL.
和正则表达式支持:
以前,MySQL使用Henry Spencer正则表达式库来支持正则表达式运算符(REGEXP,RLIKE).
正则表达式支持已使用国际Unicode组件(ICU)重新实现,它提供完整的Unicode支持并且是多字节安全的.REGEXP_LIKE()函数以REGEXP和RLIKE运算符的方式执行正则表达式匹配,这些运算符现在是该函数的同义词.此外,REGEXP_INSTR(),REGEXP_REPLACE()和REGEXP_SUBSTR()函数可用于查找匹配位置并分别执行子串替换和提取.
SELECT REGEXP_REPLACE('Stackoverflow','[A-Zf]','-',1,0,'c');
-- Output:
-tackover-low
Run Code Online (Sandbox Code Playgroud)
小智 43
我最近编写了一个MySQL函数来使用正则表达式替换字符串.你可以在以下位置找到我的帖子:
http://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/
这是功能代码:
DELIMITER $$
CREATE FUNCTION `regex_replace`(pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN
DECLARE temp VARCHAR(1000);
DECLARE ch VARCHAR(1);
DECLARE i INT;
SET i = 1;
SET temp = '';
IF original REGEXP pattern THEN
loop_label: LOOP
IF i>CHAR_LENGTH(original) THEN
LEAVE loop_label;
END IF;
SET ch = SUBSTRING(original,i,1);
IF NOT ch REGEXP pattern THEN
SET temp = CONCAT(temp,ch);
ELSE
SET temp = CONCAT(temp,replacement);
END IF;
SET i=i+1;
END LOOP;
ELSE
SET temp = original;
END IF;
RETURN temp;
END$$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
执行示例:
mysql> select regex_replace('[^a-zA-Z0-9\-]','','2my test3_text-to. check \\ my- sql (regular) ,expressions ._,');
Run Code Online (Sandbox Code Playgroud)
小智 39
我们解决这个问题而不使用正则表达式这个查询只替换完全匹配字符串.
update employee set
employee_firstname =
trim(REPLACE(concat(" ",employee_firstname," "),' jay ',' abc '))
Run Code Online (Sandbox Code Playgroud)
例:
emp_id employee_firstname
1杰伊
2 jay ajay
3杰伊
执行查询结果后:
emp_id employee_firstname
1 abc
2 abc ajay
3 abc
dot*_*hen 14
我很高兴地报告说,既然问了这个问题,现在有一个满意的答案!看看这个了不起的包:
https://github.com/mysqludf/lib_mysqludf_preg
示例SQL:
SELECT PREG_REPLACE('/(.*?)(fox)/' , 'dog' , 'the quick brown fox' ) AS demo;
Run Code Online (Sandbox Code Playgroud)
Ste*_*ers 11
更新2: MySQL 8.0中现在提供了一组有用的正则表达式函数,包括REGEXP_REPLACE.除非您被限制使用早期版本,否则这会使读取变得不必要.
更新1:现在已将其变成博客文章:http://stevettt.blogspot.co.uk/2018/02/a-mysql-regular-expression-replace.html
以下内容扩展了Rasika Godawatte提供的功能,但是通过所有必要的子串搜索而不仅仅是测试单个字符:
-- ------------------------------------------------------------------------------------
-- USAGE
-- ------------------------------------------------------------------------------------
-- SELECT reg_replace(<subject>,
-- <pattern>,
-- <replacement>,
-- <greedy>,
-- <minMatchLen>,
-- <maxMatchLen>);
-- where:
-- <subject> is the string to look in for doing the replacements
-- <pattern> is the regular expression to match against
-- <replacement> is the replacement string
-- <greedy> is TRUE for greedy matching or FALSE for non-greedy matching
-- <minMatchLen> specifies the minimum match length
-- <maxMatchLen> specifies the maximum match length
-- (minMatchLen and maxMatchLen are used to improve efficiency but are
-- optional and can be set to 0 or NULL if not known/required)
-- Example:
-- SELECT reg_replace(txt, '^[Tt][^ ]* ', 'a', TRUE, 2, 0) FROM tbl;
DROP FUNCTION IF EXISTS reg_replace;
DELIMITER //
CREATE FUNCTION reg_replace(subject VARCHAR(21845), pattern VARCHAR(21845),
replacement VARCHAR(21845), greedy BOOLEAN, minMatchLen INT, maxMatchLen INT)
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN
DECLARE result, subStr, usePattern VARCHAR(21845);
DECLARE startPos, prevStartPos, startInc, len, lenInc INT;
IF subject REGEXP pattern THEN
SET result = '';
-- Sanitize input parameter values
SET minMatchLen = IF(minMatchLen < 1, 1, minMatchLen);
SET maxMatchLen = IF(maxMatchLen < 1 OR maxMatchLen > CHAR_LENGTH(subject),
CHAR_LENGTH(subject), maxMatchLen);
-- Set the pattern to use to match an entire string rather than part of a string
SET usePattern = IF (LEFT(pattern, 1) = '^', pattern, CONCAT('^', pattern));
SET usePattern = IF (RIGHT(pattern, 1) = '$', usePattern, CONCAT(usePattern, '$'));
-- Set start position to 1 if pattern starts with ^ or doesn't end with $.
IF LEFT(pattern, 1) = '^' OR RIGHT(pattern, 1) <> '$' THEN
SET startPos = 1, startInc = 1;
-- Otherwise (i.e. pattern ends with $ but doesn't start with ^): Set start pos
-- to the min or max match length from the end (depending on "greedy" flag).
ELSEIF greedy THEN
SET startPos = CHAR_LENGTH(subject) - maxMatchLen + 1, startInc = 1;
ELSE
SET startPos = CHAR_LENGTH(subject) - minMatchLen + 1, startInc = -1;
END IF;
WHILE startPos >= 1 AND startPos <= CHAR_LENGTH(subject)
AND startPos + minMatchLen - 1 <= CHAR_LENGTH(subject)
AND !(LEFT(pattern, 1) = '^' AND startPos <> 1)
AND !(RIGHT(pattern, 1) = '$'
AND startPos + maxMatchLen - 1 < CHAR_LENGTH(subject)) DO
-- Set start length to maximum if matching greedily or pattern ends with $.
-- Otherwise set starting length to the minimum match length.
IF greedy OR RIGHT(pattern, 1) = '$' THEN
SET len = LEAST(CHAR_LENGTH(subject) - startPos + 1, maxMatchLen), lenInc = -1;
ELSE
SET len = minMatchLen, lenInc = 1;
END IF;
SET prevStartPos = startPos;
lenLoop: WHILE len >= 1 AND len <= maxMatchLen
AND startPos + len - 1 <= CHAR_LENGTH(subject)
AND !(RIGHT(pattern, 1) = '$'
AND startPos + len - 1 <> CHAR_LENGTH(subject)) DO
SET subStr = SUBSTRING(subject, startPos, len);
IF subStr REGEXP usePattern THEN
SET result = IF(startInc = 1,
CONCAT(result, replacement), CONCAT(replacement, result));
SET startPos = startPos + startInc * len;
LEAVE lenLoop;
END IF;
SET len = len + lenInc;
END WHILE;
IF (startPos = prevStartPos) THEN
SET result = IF(startInc = 1, CONCAT(result, SUBSTRING(subject, startPos, 1)),
CONCAT(SUBSTRING(subject, startPos, 1), result));
SET startPos = startPos + startInc;
END IF;
END WHILE;
IF startInc = 1 AND startPos <= CHAR_LENGTH(subject) THEN
SET result = CONCAT(result, RIGHT(subject, CHAR_LENGTH(subject) + 1 - startPos));
ELSEIF startInc = -1 AND startPos >= 1 THEN
SET result = CONCAT(LEFT(subject, startPos), result);
END IF;
ELSE
SET result = subject;
END IF;
RETURN result;
END//
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
演示
限制
\1,\2
等等)来替换捕获组.如果需要此功能,请参阅此答案,该答案试图通过更新函数来提供解决方法,以允许在每个找到的匹配中进行辅助查找和替换(以增加的复杂性为代价).^和/或$在模式中使用,它们必须分别位于开始和结束 - 例如,(^start|end$)不支持的模式.a.*?b.*不支持在单个正则表达式(例如)中组合贪婪和惰性匹配.用法示例
该函数已用于回答以下StackOverflow问题:
你可以做到这一点......但这并不是很明智......这就像我会尝试的那样大胆......只要完整的RegEx支持你使用perl之类的东西就更好了.
UPDATE db.tbl
SET column =
CASE
WHEN column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]'
THEN REPLACE(column,'WORD_TO_REPLACE','REPLACEMENT')
END
WHERE column REGEXP '[[:<:]]WORD_TO_REPLACE[[:>:]]'
Run Code Online (Sandbox Code Playgroud)
我们可以在SELECT查询中使用IF条件,如下所示:
假设对于任何带有"ABC","ABC1","ABC2","ABC3",......的东西,我们想用"ABC"替换然后在SELECT查询中使用REGEXP和IF()条件,我们可以实现这一点.
句法:
SELECT IF(column_name REGEXP 'ABC[0-9]$','ABC',column_name)
FROM table1
WHERE column_name LIKE 'ABC%';
Run Code Online (Sandbox Code Playgroud)
例:
SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');
Run Code Online (Sandbox Code Playgroud)
我认为有一种简单的方法可以实现这一目标,而且对我来说效果很好。
使用 REGEX 选择行
SELECT * FROM `table_name` WHERE `column_name_to_find` REGEXP 'string-to-find'
Run Code Online (Sandbox Code Playgroud)
使用 REGEX 更新行
UPDATE `table_name` SET column_name_to_find=REGEXP_REPLACE(column_name_to_find, 'string-to-find', 'string-to-replace') WHERE column_name_to_find REGEXP 'string-to-find'
Run Code Online (Sandbox Code Playgroud)
REGEXP 参考:https : //www.geeksforgeeks.org/mysql-regular-expressions-regexp/
| 归档时间: |
|
| 查看次数: |
419117 次 |
| 最近记录: |