【问题标题】:Replacing old urls with new ones用新网址替换旧网址
【发布时间】:2017-06-30 10:36:06
【问题描述】:

我有一个来自数据库的字符串,其中包含一些 url。我正在尝试用新网址替换旧网址。因为包含 url 的字符串的格式是 {s:5:"hello"},所以我还需要用新的字符串长度替换旧的字符串长度。

我试过了

var url    = "http://localhost/arearaf";
var text   = "somelongstring; 35; '%site_url%'; s:46:\"%site_url%/wp-content/uploads/2017/06/logo.png\"; someotherlongstring; s:54:\"%site_url%/wp-content/uploads/2017/06/logo-150x150.png\";";
var result = Regex.Replace(text, @"s:\d+:\" + "\"%site_url%(.*?)\";", "s:" + (url.Length + "$1".Length) + @":\" + "\"" + url + "$1" + @"\" + "\";");

导致

"somelongstring; 35; '%site_url%'; s:26:\"http://localhost/arearaf/wp-content/uploads/2017/06/logo.png\"; someotherlongstring; s:26:\"http://localhost/arearaf/wp-content/uploads/2017/06/logo-150x150.png\";"

但应该是

"somelongstring; 35; '%site_url%'; s:60:\"http://localhost/arearaf/wp-content/uploads/2017/06/logo.png\"; someotherlongstring; s:68:\"http://localhost/arearaf/wp-content/uploads/2017/06/logo-150x150.png\";"

"$1".Length 显然不会返回 "/wp-content/uploads/2017/06/logo.png".Length。如何获取每个替换的捕获组的长度?我是否也正确处理了这个问题?如果没有,我该怎么办?


这种格式{s:5:"hello"}不是有名字什么的吗?我不能谷歌它。我能找到的最接近的东西是 CMS,它代表内容管理系统,我猜?不过,还不够。

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    使用匹配评估器并按以下方式修改代码:

    var url    = "http://localhost/arearaf";
    var text   = "somelongstring; 35; '%site_url%'; s:46:\"%site_url%/wp-content/uploads/2017/06/logo.png\"; someotherlongstring; s:54:\"%site_url%/wp-content/uploads/2017/06/logo-150x150.png\";";
    var result = Regex.Replace(text, "s:\\d+:\"%site_url%(.*?)\";", m =>
            $"s:{url.Length + m.Groups[1].Value.Length}:\"{url}{m.Groups[1].Value}\";");
    Console.WriteLine(result);
    // => somelongstring; 35; '%site_url%'; s:60:"http://localhost/arearaf/wp-content/uploads/2017/06/logo.png"; someotherlongstring; s:68:"http://localhost/arearaf/wp-content/uploads/2017/06/logo-150x150.png";
    

    online demo

    模式 (s:\d+:"%site_url%(.*?)";):

    • s: - 一个子字符串 s:
    • \d+ - 1 个或多个数字(使用 RegexOptions.ECMAScript 编译以仅匹配 ASCII 数字)
    • :" - :"%site_url% 子字符串
    • (.*?) - 第 1 组捕获除换行符以外的任何 0 个或多个字符(如果您也需要匹配换行符,请传递 RegexOptions.Singleline
    • "; - 一个子字符串 ";

    匹配评估器将匹配对象传递给内插字符串字面量:

    • $" - 内插字符串文字开始
    • s: - 文字 s:
    • {url.Length + m.Groups[1].Value.Length} - URL 长度和 Group 1 值长度相加并转换为字符串的插值部分
    • :\" - :" 子字符串
    • {url} - url 变量值
    • {m.Groups[1].Value} - 第 1 组值
    • \"; - "; 子字符串
    • " - 字符串文字的结尾。

    对于不支持内插字符串文字的旧环境,请使用string.Format

    var result = Regex.Replace(text, "s:\\d+:\"%site_url%(.*?)\";", m =>
      string.Format("s:{0}:\"{1}{2}\";", 
        url.Length + m.Groups[1].Value.Length, url, m.Groups[1].Value));
    

    【讨论】:

    • 我正在使用 Visual C# 2010 Express 并收到此错误“无法将 lambda 表达式转换为类型 'int',因为它不是委托类型”。我错过了什么?
    • 4 客户资料。我应该改变它吗?
    • 好的,看起来 lambdas 没问题,但是您的 IDE 不支持内插字符串文字。将$"" 更改为string.Format。查看我的最新编辑。
    猜你喜欢
    • 2016-11-28
    • 1970-01-01
    • 2021-11-03
    • 2021-10-21
    • 2016-11-03
    • 2016-11-22
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    相关资源
    最近更新 更多