Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在MySQL中替换正则表达式?_Mysql_Regex_Mysql Udf_Mysql 5.6 - Fatal编程技术网

如何在MySQL中替换正则表达式?

如何在MySQL中替换正则表达式?,mysql,regex,mysql-udf,mysql-5.6,Mysql,Regex,Mysql Udf,Mysql 5.6,我有一张约500k行的桌子;varchar(255)UTF8列文件名包含一个文件名 我试图从文件名中去掉各种奇怪的字符-我想我应该使用一个字符类:[^a-zA-Z0-9()。\-] 现在,MySQL中是否有一个函数允许您通过正则表达式进行替换?我正在寻找一个类似的函数来替换()函数-简化示例如下: SELECT REPLACE('stackowerflow', 'ower', 'over'); Output: "stackoverflow" /* does something like th

我有一张约500k行的桌子;varchar(255)UTF8列
文件名
包含一个文件名

我试图从文件名中去掉各种奇怪的字符-我想我应该使用一个字符类:
[^a-zA-Z0-9()。\-]

现在,MySQL中是否有一个函数允许您通过正则表达式进行替换?我正在寻找一个类似的函数来替换()函数-简化示例如下:

SELECT REPLACE('stackowerflow', 'ower', 'over');

Output: "stackoverflow"

/* does something like this exist? */
SELECT X_REG_REPLACE('Stackoverflow','/[A-Zf]/','-'); 

Output: "-tackover-low"
我知道,但这些只是检查是否有匹配,而不是匹配是什么

(我可以从PHP脚本中执行“
选择pkey\u id,文件名来自foo,其中文件名类似“[^a-zA-Z0-9()\.-]”
”,执行
preg\u replace
,然后“
更新foo…其中pkey\u id=…
”,但这看起来像是最后一个缓慢而丑陋的黑客手段)

MySQL 8.0+: 您可以使用本机函数

旧版本:
您可以使用用户定义函数(UDF),如。

我最近编写了一个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 ;
执行示例:

mysql> select regex_replace('[^a-zA-Z0-9\-]','','2my test3_text-to. check \\ my- sql (regular) ,expressions ._,');

我用蛮力的方法让它工作就是:

  • 转储表-
    mysqldump-u user-p database table>Dump.sql
  • 查找并替换一对模式-
    Find/path/to/dump.sql-type f-exec sed-i's/old_string/new_string/g'{}\
    
  • 导入表-
    mysqlimport-u user-p数据库表

  • 如果要确保字符串不在数据集中的其他位置,请运行一些正则表达式,以确保它们都出现在类似的环境中。在运行替换之前创建备份也不是那么困难,以防您意外地破坏了某些丢失深度信息的内容

    你“能”做到。。。但这不是很明智。。。这是我要尝试的最大胆的事。。。就完全正则表达式支持而言,最好使用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[[:>:]]'
    
    更新db.tbl
    设置列=
    案例
    当列REGEXP“[[::]”时
    然后替换(列,'WORD_TO_REPLACE','REPLACEMENT')
    终止
    其中列REGEXP“[[::]”
    
    我很高兴地报告,既然有人问了这个问题,现在有了令人满意的答案!看看这个很棒的套餐:

    示例SQL:

    SELECT PREG_REPLACE('/(.*?)(fox)/' , 'dog' , 'the quick brown fox' ) AS demo;
    

    我从上的链接中找到了该包。

    如果您使用的是MariaDB或MySQL 8.0,则它们有一个函数

    REGEXP_REPLACE(col, regexp, replace)
    
    看到和

    请注意,您也可以使用regexp分组(我发现这非常有用):

    返回

    over - stack - flow
    

    我们可以在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%';
    
    例如:

    SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');
    

    我们不使用正则表达式就解决了这个问题 此查询仅替换完全匹配的字符串

    update employee set
    employee_firstname = 
    trim(REPLACE(concat(" ",employee_firstname," "),' jay ',' abc '))
    
    例如:

    SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');
    
    emp_id员工名

    1杰伊

    2杰伊·阿杰

    3杰伊

    执行查询结果后:

    emp_id员工名

    1 abc

    2 abc ajay

    3 abc


    更新2:MySQL 8.0中现在提供了一组有用的正则表达式函数,包括。这使得阅读变得不必要,除非您必须使用早期版本


    更新1:已将此内容写入博客帖子:


    以下内容扩展了,但拖网了所有必要的子字符串,而不仅仅是测试单个字符:

    -- ------------------------------------------------------------------------------------
    -- 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 IS NULL OR minMatchLen < 1, 1, minMatchLen);
        SET maxMatchLen = IF(maxMatchLen IS NULL OR 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 ;
    
    ——------------------------------------------------------------------------------------
    --用法
    -- ------------------------------------------------------------------------------------
    --选择reg_replace(,
    --                    ,
    --                    ,
    --                    ,
    --                    ,
    --                    );
    --其中:
    --要查找以进行替换的字符串
    --是要匹配的正则表达式
    --是替换字符串
    --对于贪婪匹配为TRUE,对于非贪婪匹配为FALSE
    --指定最小匹配长度
    --指定最大匹配长度
    --(minMatchLen和maxMatchLen用于提高效率,但不适用
    --可选,如果不知道/不需要,可以设置为0或NULL)
    --例如:
    --从tbl中选择reg_replace(txt,“^[Tt][^]*”,“a',TRUE,2,0);
    删除功能(如果存在)reg_replace;
    分隔符//
    创建函数reg_replace(主体VARCHAR(21845)、模式VARCHAR(21845),
    替换VARCHAR(21845)、贪婪布尔、minMatchLen INT、maxMatchLen INT)
    返回VARCHAR(21845)值
    声明结果,subStr,usePattern VARCHAR(21845);
    声明startPos、previstartpos、startInc、len、lenic INT;
    如果主题是REGEXP模式,那么
    设置结果=“”;
    --清理输入参数值
    设置minMatchLen=IF(minMatchLen为NULL或minMatchLen<1,1,minMatchLen);
    设置maxMatchLen=IF(maxMatchLen为NULL或maxMatchLen<1
    或maxMatchLen>字符长度(主题),
    字符长度(主题),最大匹配长度;
    --设置用于匹配整个字符串而不是字符串的一部分的模式
    设置usePattern=IF(左(pattern,1)='^',pattern,CONCAT('^',pattern));
    设置usePattern=IF(右(pattern,1)='$',usePattern,CONCAT(usePattern'$);
    --如果模式以^开头或不以$结尾,则将“开始位置”设置为1。
    如果左(模式1)='^'或右(模式1)'$',则
    设置startPos=1,startInc=1;
    --否则(即模式以$结尾,但不以^开头):设置开始位置
    --至末端的最小或最大匹配长度(取决于“贪婪”标志)。
    艾尔塞夫那么贪婪
    设置startPos=CHAR_LENGTH(主题)-maxMatchLen+1,startInc=1;
    其他的
    s
    
    SELECT REGEXP_REPLACE('Stackoverflow','[A-Zf]','-',1,0,'c'); 
    -- Output:
    -tackover-low
    
    SELECT REGEX_REPLACE('dis ambiguity', 'dis[[:space:]]*ambiguity', 'disambiguity');
    
    DELIMITER $$
    CREATE FUNCTION REGEX_REPLACE(
      var_original VARCHAR(1000),
      var_pattern VARCHAR(1000),
      var_replacement VARCHAR(1000)
      ) RETURNS
        VARCHAR(1000)
      COMMENT 'Based on https://techras.wordpress.com/2011/06/02/regex-replace-for-mysql/'
    BEGIN
      DECLARE var_replaced VARCHAR(1000) DEFAULT var_original;
      DECLARE var_leftmost_match VARCHAR(1000) DEFAULT
        REGEX_CAPTURE_LEFTMOST(var_original, var_pattern);
        WHILE var_leftmost_match IS NOT NULL DO
          IF var_replacement <> var_leftmost_match THEN
            SET var_replaced = REPLACE(var_replaced, var_leftmost_match, var_replacement);
            SET var_leftmost_match = REGEX_CAPTURE_LEFTMOST(var_replaced, var_pattern);
            ELSE
              SET var_leftmost_match = NULL;
            END IF;
          END WHILE;
      RETURN var_replaced;
    END $$
    DELIMITER ;
    
    DELIMITER $$
    CREATE FUNCTION REGEX_CAPTURE_LEFTMOST(
      var_original VARCHAR(1000),
      var_pattern VARCHAR(1000)
      ) RETURNS
        VARCHAR(1000)
      COMMENT '
      Captures the leftmost substring that matches the [var_pattern]
      IN [var_original], OR NULL if no match.
      '
    BEGIN
      DECLARE var_temp_l VARCHAR(1000);
      DECLARE var_temp_r VARCHAR(1000);
      DECLARE var_left_trim_index INT;
      DECLARE var_right_trim_index INT;
      SET var_left_trim_index = 1;
      SET var_right_trim_index = 1;
      SET var_temp_l = '';
      SET var_temp_r = '';
      WHILE (CHAR_LENGTH(var_original) >= var_left_trim_index) DO
        SET var_temp_l = LEFT(var_original, var_left_trim_index);
        IF var_temp_l REGEXP var_pattern THEN
          WHILE (CHAR_LENGTH(var_temp_l) >= var_right_trim_index) DO
            SET var_temp_r = RIGHT(var_temp_l, var_right_trim_index);
            IF var_temp_r REGEXP var_pattern THEN
              RETURN var_temp_r;
              END IF;
            SET var_right_trim_index = var_right_trim_index + 1;
            END WHILE;
          END IF;
        SET var_left_trim_index = var_left_trim_index + 1;
        END WHILE;
      RETURN NULL;
    END $$
    DELIMITER ;
    
    SELECT * FROM `table_name` WHERE `column_name_to_find` REGEXP 'string-to-find'
    
    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'
    
    UPDATE table_name 
      SET column_name = 'seach_str_name'
      WHERE column_name REGEXP '[^a-zA-Z0-9()_ .\-]';