首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >匹配控制字符之前出现的字符,如果不存在控制字符,则匹配零。

匹配控制字符之前出现的字符,如果不存在控制字符,则匹配零。
EN

Stack Overflow用户
提问于 2013-04-20 00:25:14
回答 3查看 174关注 0票数 4

我正在开发功能,允许用户为文件夹层次结构中的项指定一个“通配符”路径,并在项目匹配该路径时执行相关操作。例如:

代码语言:javascript
复制
    Path         Action
    -----------  -------
 1. $/foo/*/baz  include
 2. $/foo/bar/*  exclude

现在,使用上面的示例,$/foo/bar/baz上的一个项将匹配这两个操作。考虑到这一点,我想提供通配符路径的粗分数,这将基于第一个通配符出现的“深度”。最深邃的道路将获胜。重要的是,只有以正斜杠(/*/)为界的*才允许作为通配符(除了在结束时为/*),并且可以在路径的各个点指定任何数字。

TL;DR;

因此,我认为在第一个*之前用正则表达式来计算斜杠的数量是可行的。但是,由于许多原因,在路径中没有通配符的情况下,正斜杠的匹配将为零。我有以下负面的展望:

代码语言:javascript
复制
 (?<!\*.*)/

当有通配符(例如,上面路径#1的两个正斜杠匹配和#2的3个正斜杠匹配)时,它工作得很好,但是当没有通配符时,它自然会匹配所有正斜杠。我相信这是一个简单的步骤,没有匹配,但由于生锈的调整技能,我是卡住了。

理想情况下,从学术的角度来看,我想看看一个正则表达式是否可以捕捉到这一点,但是为更优雅的解决问题提供了额外的积分!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-20 06:45:31

这将是一种方法:

代码语言:javascript
复制
match = Regex.Match(subject, 
    @"^       # Start of string
    (         # Match and capture in group number 1...
     [^*/]*   #  any number of characters except slashes or asterisks
     /        #  followed by a slash
    )*        # zero or more times.
    [^*/]*    # Match any additional non-slash/non-asterisk characters.
    \*        # Then match an asterisk", 
    RegexOptions.IgnorePatternWhitespace);

如果subject字符串中没有星号(0分数),则此正则表达式无法匹配。如果正则表达式匹配,则可以确保其中至少有一个星号。

现在聪明的是,与大多数其他正则表达式不同,.NET正则表达式实际上可以计算重复捕获组匹配的次数(大多数其他regex引擎只是丢弃该信息),这允许我们在字符串中的第一个星号之前确定斜杠的数量。

这些信息可以在

代码语言:javascript
复制
match.Groups[1].Captures.Count

(当然,这意味着“在第一个星号之前没有斜杠”和“根本没有星号”都会得到分数0,这似乎是您在问题中要求的,但我不知道为什么这会有意义)

票数 2
EN

Stack Overflow用户

发布于 2013-04-20 01:22:21

一种能够完成这项任务的方法:

  1. 验证所有测试路径(确保它们有效,并包含\*\或end by *)。
  2. 使用排序集合跟踪测试路径和相关操作。
  3. 根据通配符在字符串中的位置对集合进行排序。
  4. 根据排序集合中的每个路径测试项。 可以将字符串中的*替换为.*?,以便在正则表达式中使用它。
  5. 在第一个匹配处停止并返回关联的操作,否则将继续进行集合中的下一个测试。

对上述一些内容的快速测试实现:

代码语言:javascript
复制
void Main()
{
    // Define some actions to test and add them to a collection
    var ActionPaths = new List<ActionPath>() {
        new ActionPath() {TestPath = "/foo/*/baz",   Action = "include"},
        new ActionPath() {TestPath = "/foo/bar/*",   Action = "exclude"},
        new ActionPath() {TestPath = "/foo/doo/boo", Action = "exclude"},
    };
    // Sort the list of actions based on the depth of the wildcard
    ActionPaths.Sort();

    // the path for which we are trying to find the corresponding action
    string PathToTest = "/foo/bar/baz";

    // Test all ActionPaths from the top down until we find something
    var found = default(ActionPath);
    foreach (var ap in ActionPaths) {
        if (ap.IsMatching(PathToTest)) {
            found = ap;
            break;
        }
    }

    // At this point, we have either found an Action, or nothing at all
    if (found != default(ActionTest)) {
        // Found an Action!
    } else {
        // Found nothing at all :-(
    }
}

// Hold and Action Test
class ActionPath : IComparable<ActionPath>
{
    public string TestPath;
    public string Action;

    // Returns true if the given path matches the TestPath
    public bool IsMatching(string path) {
        var t = TestPath.Replace("*",".*?");
        return Regex.IsMatch(path, "^" + t + "$");
    }

    // Implements IComparable<T>
    public int CompareTo(ActionPath other) {
       if (other.TestPath == null) return 1;
       var ia = TestPath.IndexOf("*");
       var ib = other.TestPath.IndexOf("*");
       if (ia < ib) return 1;       
       if (ia > ib) return -1;
       return 0;
   }
}
票数 1
EN

Stack Overflow用户

发布于 2013-04-20 03:58:56

这里不需要正则表达式。

对于LINQ,它是一条2线线:

代码语言:javascript
复制
string s = "$/foo/bar/baz";
var asteriskPos = s.IndexOf('*');  // will be -1 if there is no asterisk
var slashCount = s.Where((c, i) => c == '/' && i < asteriskPos).Count();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16115261

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档