简体   繁体   English

使用正则表达式限制字符数

[英]Limiting the number of characters using regular expression

I am using the following regular expression to turn all URLs within a string into full hyperlinks: 我使用以下正则表达式将字符串中的所有URL转换为完整的超链接:

var r = new Regex("(https?://[^ ]+)");
return r.Replace(Action, "<a target=\"_blank\" href=\"$1\">$1</a>");

I would like to limit the number of characters shown within the tags and, if possible, add ellipses if the length is exceeded. 我想限制标签中显示的字符数,如果可能的话,如果超过长度则添加省略号。

eg http://myurl.com/my/route/th ... 例如http://myurl.com/my/route/th ...

I have tried (unsuccessfully) using lookarounds to achieve this and wonder if anybody has a better solution? 我试过(不成功)使用lookarounds来实现这一点,并想知道是否有人有更好的解决方案?

The following regex would give you what you are after 以下正则表达式会给你你想要的东西

((https?://[^ ]){20}[^ ]+)

What this is doing is creating 2 capture groups 这样做是创建2个捕获组

  1. Capture the entire URL 捕获整个URL
  2. Capture the URL up to a specific length (in this example 20) 将URL捕获到特定长度(在此示例中为20)

All that's required is to add the truncation eg 所需要的只是添加截断,例如

Regex.Replace(Action, "((https?://[^ ]){20}[^ ]+)", "<a target=\"_blank\" href=\"$1\">$2...</a>"));

See it in action . 看到它在行动


As pointed out in the comments, the above would result in the ... being appended to all the URLs (even ones which don't exceed the length). 正如评论中指出的那样,上面会导致...附加到所有URL(即使是不超过长度的URL)。 Given the variability of this using only a regex here probably isn't viable. 鉴于这种使用正则表达式的可变性可能是不可行的。 We can, however, resolve this with a small tweak to the regex and some simple string manipulation eg 但是,我们可以通过对正则表达式的一些小调整和一些简单的字符串操作来解决这个问题

var match = Regex.Match(Action, "(https?://[^ ]{50})?[^ ]+");
// if the display part group has matched something, we need to truncate
var displayText = match.Groups[1].Length > 0 ? String.Format("{0}...", match.Groups[1]) : match.ToString();
Console.WriteLine(String.Format("<a target=\"_blank\" href=\"{0}\">{1}</a>", match, displayText));

I have updated the example 我已经更新了这个例子

This is best solved by a custom match evaluator , by using a function to do the replacing. 最好通过自定义匹配评估程序解决,通过使用函数进行替换。

string Action = "Somebody turn http://stackoverflow.com/questions/20494457/limiting-the-number-of-characters-using-regular-expression into a link please.";
var r = new Regex("(https?://\\S+)");
return r.Replace(Action,
    match => {
        string display = match.Value;
        if (display.Length > 30)
        {
            display = display.Substring(0, 30) + "...";
        }
        return "<a target=\"_blank\" href=\"" + match.Value + "\">" + display + "</a>";
    });

Returns: 返回:

Somebody turn <a target="_blank" href="http://stackoverflow.com/questions/20494457/limiting-the-number-of-characters-using-regular-expression">http://stackoverflow.com/quest...</a> into a link please.

I don't think it's possible to do this with a simple regex replacement, but luckily .NET allows you to perform a much more complex replacement. 我认为通过简单的正则表达式替换可以实现这一点,但幸运的是.NET允许您执行更复杂的替换。 First we set up the regex to capture the first (eg) 25 characters after the start of the URL in one group, and any further characters in a second, optional group: 首先,我们设置正则表达式以捕获一个组中URL开始后的第一个(例如)25个字符,以及第二个可选组中的任何其他字符:

var r = new Regex("(https?://[^ ]{1,25})([^ ]+)?");

This second group will fail completely if there are fewer than 25 character after the start of the URL, but it's optional so it won't make the regex as a whole fail. 如果在URL开始后少于25个字符,则第二个组将完全失败,但它是可选的,因此它不会使正则表达式整体失败。

Then, when replacing, we check whether the second group matched when deciding whether or not to add the dots: 然后,在更换时,我们在决定是否添加点时检查第二组是否匹配:

var s = r.Replace(
    Action,
    m => string.Concat(
        "<a target=\"_blank\" href=\"",
        m.Value,
        "\">",
        m.Groups[1].Value,
        (m.Groups[2].Success ? "..." : ""),
        "</a>"));

For the input 输入

"hello http://www.google.com world
 http://www.loooooooooooooooooooooooooooooooooooooooooong.com !"

I get output 我得到输出

hello <a target="_blank" href="http://www.google.com">http://www.google.com</a>
world <a target="_blank"
    href="http://www.loooooooooooooooooooooooooooooooooooooooooong.com">
    http://www.loooooooooooooooooooo...</a> !

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

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