【问题标题】:Regex to ignore trailing dot if there is one正则表达式忽略尾随点,如果有一个
【发布时间】:2016-02-01 06:38:03
【问题描述】:

我有以下正则表达式(粗略匹配看起来像 URLS 的东西)

(https?://\S*)

但是,这是在句子中提取 URL,因此尾随点可能是句子的结尾,而不是 URL 的合法部分。

让捕获组忽略尾随句号、逗号、冒号、分号等的魔法咒语是什么?

(我知道匹配 URL 是一场噩梦,这只需要支持松散匹配,因此非常简单的正则表达式)

这是我的测试字符串:

lorem http://www.example.com lorem https://example.com lorem 
http://www.example.com.
lorem https://example.com.

这应该匹配所有 example.com 实例。

(我正在使用 Expresso 和 .NET 对其进行测试)

带有尾随点和新行的测试结果:

  Expected string length 62 but was 64. Strings differ at index 31.
  Expected: "<a href="http://www.example.com">http://www.example.com</a>.\n\r"
  But was:  "<a href="http://www.example.com.\n">http://www.example.com.\n</a>\r"
  ------------------------------------------^

示例代码

public class HyperlinkParser
{
    private readonly Regex _regex =
        new Regex(
            @"(https?://\S*[^\.])");

    public string Parse(string original)
    {
        var parsed = _regex.Replace(original, "<a href=\"$1\">$1</a>");
        return parsed;
    }
}

示例测试

[TestFixture]
public class HyperlinkParserTests
{
    private readonly HyperlinkParser _parser = new HyperlinkParser();
    private const string NO_HYPERLINKS = "dummy-text";
    private const string FULL_URL = "http://www.example.com";
    private const string FULL_URL_PARSED = "<a href=\"" + FULL_URL + "\">" + FULL_URL + "</a>";
    private const string FULL_URL_TRAILING_DOT = FULL_URL + ".";
    private const string FULL_URL_TRAILING_DOT_PARSED = "<a href=\"" + FULL_URL + "\">" + FULL_URL + "</a>.";
    private const string TRAILING_DOT_AND_NEW_LINE = FULL_URL_TRAILING_DOT + "\n\r";
    private const string TRAILING_DOT_AND_NEW_LINE_PARSED = FULL_URL_TRAILING_DOT_PARSED + "\n\r";

    private const string COMPLEX_TEXT = "Leading stuff http://www.example.com.  Other stuff.";
    private const string COMPLEX_TEXT_PARSED = "Leading stuff <a href=\"http://www.example.com\">http://www.example.com</a>.  Other stuff.";

    [TestCase(NO_HYPERLINKS, NO_HYPERLINKS)]
    [TestCase(FULL_URL, FULL_URL_PARSED)]
    [TestCase(FULL_URL_TRAILING_DOT, FULL_URL_TRAILING_DOT_PARSED)]
    [TestCase(TRAILING_DOT_AND_NEW_LINE, TRAILING_DOT_AND_NEW_LINE_PARSED)]
    [TestCase(COMPLEX_TEXT, COMPLEX_TEXT_PARSED)]
    public void Parsing(string original, string expected)
    {
        var actual = _parser.Parse(original);

        Assert.That(actual, Is.EqualTo(expected));
    }
}

【问题讨论】:

  • 能否提供一个测试代码?拨弄一下IDEONE.com 会很有帮助。用空格测试字符串不是一件容易的事,我们可能会在与您不同的字符串上进行测试。
  • @WiktorStribiżew 我已经添加了代码,我无法在在线小提琴上进行解析。通过在[^\.] 的位置中使用[^\W],我已经成功地完成了这项工作。

标签: .net regex


【解决方案1】:

试试这个,它禁止点作为最后一个字符:

(https?://\S*[^.])

例如在cygwin下,用egrep:

$ cat ~/tmp.txt
lorem http://www.example.com lorem https://example.com lorem
http://www.example.com.
lorem https://example.com.
$ cat ~/tmp.txt | egrep -o 'https?://\S*[^.]'
http://www.example.com
https://example.com
http://www.example.com
https://example.com

-o 选项告诉 egrep 只打印匹配项。)

【讨论】:

  • 由于某种原因,现在匹配 http://www.example.com.[CR](CR = 回车)
  • 您是否还想输入[^\.]
  • 那为什么我会同时捕获点和新行呢?这很奇怪。我正在使用 .NET 实现,如果这意味着什么的话。
  • 我不知道你的环境有什么问题,但据此它也应该适用于 .NET:regexstorm.net/tester?p=(https%3f%3a%2f%2f%5cS*%5b%5e.%5d)&i=lorem+http% 3a%2f%2fwww.example.com+lorem+https%3a%2f%2fexample.com+lorem+%0d%0ahttp%3a%2f%2fwww.example.com.%0d%0alorem+https%3a%2f%2fexample .com.
  • 看一下第二场比赛,它正在拾取点和(我怀疑)新行。新线路似乎有所作为。
猜你喜欢
  • 2017-01-17
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-10
  • 1970-01-01
  • 2014-01-02
相关资源
最近更新 更多