简体   繁体   English

如何在 MySQL 文本字段中查找和替换整个单词?

[英]How to find and replace whole words in a MySQL text field?

I have a sentence:我有一句话:

"How to find and replace word in text from mysql database?" “如何从mysql数据库中查找和替换文本中的单词?”

And MySQL table words, with to 3 column id, word and replaceWord.和MySQL表words一样,有3列id、word和replaceWord。 I have more than 4000 words in databese.我在数据库中有 4000 多个单词。

Table:表:

id     word     replaceWord
 1     text     sentence
 2     word     letter
 3     mysql    MySQL
 4     ..       ...
 5     ..       ...
 6     ..       ...

Result:结果:

"How to find and replace letter in sentence from MySQL database?" “如何从MySQL数据库中查找和替换句子中的字母?”

I know how to do this without database, but i need database.我知道如何在没有数据库的情况下执行此操作,但我需要数据库。

 <?php
$text="How to find and replace word in text from mysql database?";
$replaceWord=array(  "text" => "sentence", "word" => "letter", "mysql" => "MySQL");
echo strtr($tekst, $replaceWord);
?>
update YourTable, Words
    set YourTable.YourColumn = replace(YourTable.YourColumn, Words.word, Words.replaceWord)

MySQL 8+ MySQL 8+

This can be done easily enough with the REGEXP_REPLACE function:这可以通过REGEXP_REPLACE函数轻松完成:

SELECT REGEXP_REPLACE(the_text,
                      CONCAT('(^|\\W)', text_to_find, '(\\W|$)'),
                      CONCAT('$1', replacement_text, '$2')) AS replaced_text
FROM the_table;

See this dbfiddle demo .请参阅此 dbfiddle 演示

Explanation: \\W is a regular expression syntax for a non-word character (the backslash needs to be escaped hence \\\\W ).说明: \\W是非单词字符的正则表达式语法(反斜杠需要转义,因此\\\\W )。 Alternatively, ^ caters for the very start of the text and $ the very end of the text.或者, ^用于文本的最开始,而$用于文本的最后。 $1 and $2 put these characters from the parenthesized capturing groups back into the replacement text. $1$2将括号中的捕获组中的这些字符放回替换文本中。

MySQL versions prior to 8 MySQL 8 之前的版本

If you are forced to use an earlier version of MySQL it is quite a lot trickier but still technically possible using a custom written regular expression replacer - see this answer for details.如果您被迫使用较早版本的 MySQL,那么使用自定义编写的正则表达式替换器在技术上仍然可行 - 有关详细信息,请参阅此答案


MariaDB 10.0.5+ MariaDB 10.0.5+

As pointed out by Paul Spiegel in the comments, the only difference in MariaDB versions supporting REGEXP_REPLACE is the use of \\\\1 and \\\\2 instead of $1 and $2 to identify the capturing groups:正如 Paul Spiegel 在评论中指出的,支持REGEXP_REPLACE MariaDB 版本的唯一区别是使用\\\\1\\\\2而不是$1$2来识别捕获组:

SELECT REGEXP_REPLACE(the_text,
                      CONCAT('(^|\\W)', text_to_find, '(\\W|$)'),
                      CONCAT('\\1', replacement_text, '\\2')) AS replaced_text
FROM the_table;

See this dbfiddle demo .请参阅此 dbfiddle 演示

//load all replacements
$result = mysql_query("SELECT * FROM YourTableNameHere");
//replace all words
$words = array();
$replacewords =array();
while ($row = mysql_fetch_assoc($result)) {
    $words[] = $row['word'];
    $replacewords[] = $row['replaceword'];
}
$text = str_replace($words,$replacewords);

If you need preg_replace as well: You must add the column isPattern to your table, then you can do this:如果您还需要 preg_replace:您必须将列 isPattern 添加到您的表中,那么您可以这样做:

//load all replacements
$result = mysql_query("SELECT * FROM YourTableNameHere");
//replace all words
$words = array();
$replacewords = array();
$preg_words = array();
$preg_replacewords = array();
while ($row = mysql_fetch_assoc($result)) {
    if(!$row['isPattern']){        
        $words[] = $row['word'];
        $replacewords[] = $row['replaceword'];
    }
    else{
        $preg_words[] = $row['word'];
        $preg_replacewords[] = $row['replaceword'];
    }
}
$text = str_replace($words,$replacewords);
$text = $preg_replace($preg_words,$preg_replacewords);
select REPLACE(fieldOrString, SearchString, ReplaceString) from table

Here's a terrible idea in terms of scalability: you could just iterate over the sentence word by word, and on each one do a query for where the word exists in 'word'.在可扩展性方面,这是一个糟糕的想法:您可以逐字遍历句子,并在每个句子上查询单词在“单词”中的位置。 If it does exist (returns data) then do a replace with the content from 'replaceWord'如果它确实存在(返回数据),则使用“replaceWord”中的内容进行替换

EDIT : Not totally database based, but more so than your current version.编辑:不完全基于数据库,但比您当前的版本更多。

Please do run the following query. 请执行以下查询。 It is working. 这是工作。

update YourTable, Words set YourTable.YourColumn = replace(YourTable.YourColumn, Words.word, Words.replaceWord) 更新YourTable,Words设置YourTable.YourColumn = replace(YourTable.YourColumn,Words.word,Words.replaceWord)

After I started to implement my own query based on the answer by @SteveChambers I found the substitution happened only once per result row.在我开始根据@SteveChambers回答实现我自己的查询后我发现每个结果行只发生了一次替换。 For example, given the table records mentioned by the OP , this query:例如,给定OP提到的表记录,这个查询:

SELECT 
    word,
    replaceWord,
    REGEXP_REPLACE(
        'How to find and replace word in text from mysql database?', 
        CONCAT('(?i)(^|\\W)', word, '(\\W|$)'),
        CONCAT('\\1', replaceWord, '\\2')
    ) AS replaced_text 
FROM 
    words 
WHERE 
    'How to find and replace word in text from mysql database?' REGEXP CONCAT('(?i)(^|\\W)', word, '(\\W|$)');

would return distinct 3 rows of results:将返回不同的 3 行结果:

word  | replaceWord | replaced_text
------+-------------+--------------
text  | sentence    | How to find and replace letter in text from mysql database?
word  | letter      | How to find and replace word in sentence from mysql database?
mysql | MySQL       | How to find and replace word in text from MySQL database?

Notice each row has only one word replaced.请注意,每一行仅替换了一个单词。

After some discussion, we got to the conclusion that recursion was required.经过一番讨论,我们得出结论,需要递归。 I managed to achieve that without a procedure or function with the following query:我设法通过以下查询在没有过程或函数的情况下实现了这一点:

SELECT 
    (@i := @i + 1) AS i, 
    @tmp := IFNULL(
        REGEXP_REPLACE(
            @tmp, 
            CONCAT('(?i)(^|\\W)', word, '(\\W|$)'), 
            CONCAT('\\1', replaceWord, '\\2')
        ),
        @tmp
    ) AS replaced_text 
FROM 
    (
        SELECT 
            @tmp := 'How to find and replace word in text from mysql database?',
            @i := 0
    ) x
LEFT JOIN 
    words 
ON 
    @tmp REGEXP CONCAT('(?i)(^|\\W)', word, '(\\W|$)') 
ORDER BY i DESC 
LIMIT 1;

This query recursively replaces each word in the original string, accumulating the replacements.此查询递归地替换原始字符串中的每个单词,累积替换。 It uses an index ( @i ) to number the rows.它使用索引 ( @i ) 对行进行编号。 Finally, it returns only the last result (greater index), which contains all accumulate replacements.最后,它只返回最后一个结果(更大的索引),其中包含所有累积替换。

It uses a LEFT JOIN combined with IFNULL to return the original string in case no substitution is made.它使用LEFT JOIN结合IFNULL来返回原始字符串,以防没有进行替换。

$tablesarray include column array where you want to search Any word or letter $tablesarray 包含要搜索的列数组 任何单词或字母

$PDO database connection $PDO 数据库连接

    $tablesarray['tablename1']= array('column1' ,'column2' );
    $tablesarray['tablename2']= array('column1' ,'column2' );
    
    $wordstoreplace = ['searchedwordOrLetter1'=>'replacedwordOrLetter1' , 'searchedwordOrLetter2'=>'replacedwordOrLetter2' ]
    foreach($repairkeyarray as $table => $columns){
        foreach($columns as $column){
            foreach($wordstoreplace as $searched => $replaced ){
                $PDO->query("update $table set `$column` = replace(`$column`, '$searched', '$replaced') WHERE `$column` LIKE '%$searched%';");
                @$PDO->execute();
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM