当前位置: 首页 > 面试题库 >

MySQL替换给定域的.html链接

薛寒
2023-03-14
问题内容

在我的数据库中,contenfields具有许多内部链接。我必须将链接结构从www.mydomain.de/page.html更改为www.mydomain.de/page/,但是replace语句应尊重该域:

这是预期将被替换的内容:

www.mydomain.de/somepage.html -> www.mydomain.de/page/
www.mydomain.de/subfolder/page.html -> www.mydomain.de/subfolder/page/
www.mydomain.de/link.html?param=1 -> www.mydomain.de/page/?param=1
www.mydomain.de/another-link.html#hash -> www.mydomain.de/page/#hash

所有其他链接都应保持不变,此处提供一些示例,但也可以是网络上的任何链接:

 www.some-domain.de/link.html    
 www.another-domain.com/somelink.html

一个内容字段中可以有不同的链接:

<p>If you want to read more, click 
<a href="http://www.mydomain.de/page.html">here</a> 
or there <a href="http://www.another-domain.com/somelink.html">there</a>

这是在做替换:

UPDATE tablename 
SET contentfield = REPLACE(contentfield, '.html', '/')

我的想法(但不知道如何为它们创建语句):

  • 在前100个字符中的哪里找到“ mydomain.de”
  • 找到“ .html”的数量=找到“ mydomain.de”的数量

不一定要100%匹配所有“ mydomain.de”链接,我对90%的比例感到满意,但外部链接中应该没有错误的替换。


问题答案:

更新: 现在已将其发布到博客文章中:http : //stevettt.blogspot.co.uk/2018/02/a-mysql-
regular-expression-
replace.html

请查看以下Rextester Fiddle,我认为它应该产生您要求的所有结果:

Rextester演示

解释

为此,需要使用模式替换功能,但是不幸的是,MySQL没有提供这种功能。因此,我写了一个(基于另一个还不够),并将其张贴在这里。如参考答案中所述,此功能的局限性在于不允许使用反向引用替换捕获组。因此,它已经在小提琴中稍作调整,以采用其他参数,使其能够在找到的替换匹配项中执行递归替换。(请注意,根据此出色的答案,在正则表达式中使用了允许的URL路径字符)。

更新SQL

以下SQL将使用以下函数更新表数据:

UPDATE urls
SET url = reg_replace(
  url,
  'www\\.mydomain\\.de/[-A-Za-z0-9\\._~!\\$&''\\(\\)\\*\\+,;=:@%/]+\\.html',
  '/[^/]+\\.html',
  '/page/',
  TRUE,
  22, -- Min match length = www.mydomain.de/?.html = 22
  0,  -- No max match length
  7,  -- Min sub-match length = /?.html = 7
  0   -- No max sub-match length
  );

功能码

演示中使用的UDF代码也发布在下面。注意:UDF委托给存储过程,因为只有存储过程才允许在MySQL中进行递归。

-- ------------------------------------------------------------------------------------
-- USAGE
-- ------------------------------------------------------------------------------------
-- SELECT reg_replace(<subject>,
--                    <pattern>,
--                    <subpattern>,
--                    <replacement>,
--                    <greedy>,
--                    <minMatchLen>,
--                    <maxMatchLen>,
--                    <minSubMatchLen>,
--                    <maxSubMatchLen>);
-- where:
-- <subject> is the string to look in for doing the replacements
-- <pattern> is the regular expression to match against
-- <subpattern> is a regular expression to match against within each
--              portion of text that matches <pattern>
-- <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
-- <minSubMatchLen> specifies the minimum match length
-- <maxSubMatchLen> specifies the maximum match length
-- (minMatchLen, maxMatchLen, minSubMatchLen and maxSubMatchLen 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, '[A-Z0-9]{3}', '[0-9]', '_', TRUE, 3, 3, 1, 1) FROM tbl;
DROP FUNCTION IF EXISTS reg_replace;
DELIMITER //
CREATE FUNCTION reg_replace(subject VARCHAR(21845), pattern VARCHAR(21845),
  subpattern VARCHAR(21845), replacement VARCHAR(21845), greedy BOOLEAN,
  minMatchLen INT, maxMatchLen INT, minSubMatchLen INT, maxSubMatchLen INT)
RETURNS VARCHAR(21845) DETERMINISTIC BEGIN
  DECLARE result VARCHAR(21845);
  CALL reg_replace_worker(
    subject, pattern, subpattern, replacement, greedy, minMatchLen, maxMatchLen,
    minSubMatchLen, maxSubMatchLen, result);
  RETURN result;
END;//
DELIMITER ;

DROP PROCEDURE IF EXISTS reg_replace_worker;
DELIMITER //
CREATE PROCEDURE reg_replace_worker(subject VARCHAR(21845), pattern VARCHAR(21845),
  subpattern VARCHAR(21845), replacement VARCHAR(21845), greedy BOOLEAN,
  minMatchLen INT, maxMatchLen INT, minSubMatchLen INT, maxSubMatchLen INT,
  OUT result VARCHAR(21845))
BEGIN
  DECLARE subStr, usePattern, useRepl VARCHAR(21845);
  DECLARE startPos, prevStartPos, startInc, len, lenInc INT;
  SET @@SESSION.max_sp_recursion_depth = 2;
  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
          IF subpattern IS NULL THEN
            SET useRepl = replacement;
          ELSE
            CALL reg_replace_worker(subStr, subpattern, NULL, replacement, greedy, 
                          minSubMatchLen, maxSubMatchLen, NULL, NULL, useRepl);
          END IF;
          SET result = IF(startInc = 1,
                          CONCAT(result, useRepl), CONCAT(useRepl, 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;
END;//
DELIMITER ;


 类似资料:
  • 问题内容: 不过,这是一个设计:例如,我放置了一个链接,例如 http://example.com 在 textarea中 。我如何获取PHP以检测它是一个链接,然后将其打印为 我记得以前做过这样的事情,但这并不是傻瓜式的证明,它会因为复杂的链接而中断。 修复它 这只是一个经过深思熟虑的.. stackoverflow也可能会使用它:D 有任何想法吗 问题答案: 让我们看一下需求。您有一些用户提供

  • 本文向大家介绍MySQL批量替换HTML标签,包括了MySQL批量替换HTML标签的使用技巧和注意事项,需要的朋友参考一下 1 前因 前段时间维护的一个WordPress小网站被黑,分析源码发现内容中多出了一段JavaScript代码: 访问页面的时候,会跳转到黑客的广告页面: 经过追踪,最后发现是在MySQL中被注入了以上代码,所以需要在wp_posts表中把这些内容都替换掉 (当然后来加强了这

  • 问题内容: 我正在尝试通过将包含某些URL的String替换为与浏览器兼容的链接URL来做一些事情。 我最初的String看起来像这样: 我想要得到的是一个看起来像这样的字符串: 我可以使用以下代码行捕获URL: 也许regexp表达式需要一些更正,但是它工作正常,需要进一步测试。 因此,问题是如何保持正则表达式捕获表达式并仅添加创建链接所需的内容:catched string 预先感谢您的关注和

  • 它是在Android上的,在加载到WebView之前需要修复html。 这可以在JAVA内部完成还是必须在WebView的JavaScript内部完成?

  • 我正在为我的站点编写一个wordpress插件,它根据同一帖子下的另一个自定义域的值替换(或者添加(如果它为空的话)自定义域的值。 示例:我将有一个带有逗号分割值的列表,如下所示: 苹果、红香蕉、黄猕猴桃、绿色等。 当我运行该脚本时,它将找到一个带有custom_field_fruit的帖子,其值为“apple”,并将custom_field_color的值更改为red,当然,在同一帖子中。然后,

  • 问题内容: 我刚刚完成了从数据库中剥离HTML实体的任务,因为我们进行了很多爬网,并且某些爬网程序在输入时没有这样做:( 因此,我开始编写一堆看起来像这样的查询; 显然,这是一种非常幼稚的方法。我一直在尝试找出解码功能是否可以做些聪明的事情。也许通过正则表达式抓住HTML实体一样,然后通过 刚刚 的部分到ASCII解码器,以及重建串…或东西… 我可以按查询继续吗?其中可能只有40个左右。 问题答案