【问题标题】:Extract all allowed characters from a regular expression从正则表达式中提取所有允许的字符
【发布时间】:2017-08-22 19:22:02
【问题描述】:

我需要从给定的正则表达式中提取所有允许的字符列表。

例如,如果正则表达式看起来像这样(一些随机示例):

[A-Z]*\s+(4|5)+

输出应该是

ABCDEFGHIJKLMNOPQRSTUVWXYZ45

(省略空格)

一个明显的解决方案是定义一组完整的允许字符,并使用find 方法返回每个字符的相应子序列。不过,这似乎是一个有点枯燥的解决方案。

谁能想到一个(可能很简单的)算法来实现这个?

【问题讨论】:

  • 您需要代码(使用哪种语言?)还是只是一个想法?你有没有想过?
  • 我实际上只是在寻找一个想法。它所使用的语言并不那么重要。
  • 所以基本上你要求的是一种被称为正则表达式解释器的算法......我认为你不会得到任何正确的答案......你真正需要做的是非常了解正则表达式很好(如果你不这样做)并相应地实现你的解释器。该算法将是,从正则表达式的左侧开始读取并读取到正则表达式的末尾,同时解释当前和之前和之后的字符
  • 这里没有简单的解决方案......你的任务将接近于制作一个正则表达式引擎......除非你找到任何开源引擎(你可以用谷歌搜索一下)
  • 我偶然发现的一个 Java 库能够执行该任务。但由于它不是问题的答案,我将其作为评论发布,因为它可能对某人有所帮助:brics.dk/automaton/index.html 有了这个你可以做Automaton automaton = new RegExp(regex).toAutomaton();,然后用Set<String> strings = automaton.singleChars().getFiniteStrings(); 检索一组字符跨度>

标签: regex string


【解决方案1】:

你可以做的一件事是:

  • 按子组拆分正则表达式
  • 针对子组测试 char 面板

看下面的例子(还不完美):

static void Main(String[] args)
{
    Console.WriteLine($"-->{TestRegex(@"[A-Z]*\s+(4|5)+")}<--");
}

public static string TestRegex(string pattern)
{
    string result = "";
    foreach (var subPattern in Regex.Split(pattern, @"[*+]"))
    {
        if(string.IsNullOrWhiteSpace(subPattern))
            continue;
        result += GetAllCharCoveredByRegex(subPattern);
    }
    
    return result;
}

public static string GetAllCharCoveredByRegex(string pattern)
{
    Console.WriteLine($"Testing {pattern}");
    var regex = new Regex(pattern);
    var matches = new List<char>();
    for (var c = char.MinValue; c < char.MaxValue; c++)
    {

        if (regex.IsMatch(c.ToString()))
        {
            matches.Add(c);
        }
    }
    return string.Join("", matches);
}

哪些输出:

测试 [A-Z]

测试\s

测试 (4|5)

-->ABCDEFGHIJKLMNOPQRSTUVWXYZ

? ? ?????? 45

【讨论】:

  • 我一开始也是这么想的。但为了涵盖整个正则表达式语法(即 ECMAScript 正则表达式语法),它必须进行大量改进。它也相当慢,因为测试所有字符非常耗时
  • @super-qua 这是一种蛮力方法,根据定义会很慢。它的优点是不需要编写正则表达式解析器......
  • 是的,这当然是正确的,我并不是说这个答案不正确。但这或多或少是我在问题中提到的方法
猜你喜欢
  • 2012-08-02
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多