Skip to content

Glob class followed by a literal ] swallows it: *[[][0-9]] matches "items[3" but not "items[3]" #172

Closed

Description

@matt-edmondson

What's wrong

When a bracket class is followed directly by a literal ], DotNet.Glob reads that ] as part of the class instead of as the next character. The class becomes "these members or ]", and the pattern needs one character fewer than the user wrote.

ExpandGlobClasses (TextFilter/TextFilter.cs, FindGlobClassEnd) correctly closes the class at the first ]. It then appends the rest of the token unchanged, so DotNet.Glob still sees ]] and misreads it. When the class gets rewritten as a list, the two readings disagree too. *[[][0-9a-f]] is expanded to *[[][0123456789abcdef]], and through TextFilter that matches "h[c" (True), while plain DotNet.Glob on the unexpanded pattern gives False.

The most natural way to search for an indexed name hits this: [[] for a literal [, a class for the index, then ].

Failure scenario

I compiled TextFilter.cs at f681291 against DotNet.Glob 3.1.3 and ran IsMatch(text, pattern, Glob, ByWholeString):

Pattern Text Actual Expected
*[[][0-9]] items[3] False True
*[[][0-9]] items[3 True False
[a]] a] False True
[a]] a True False
[ab]] b] False True
[!a]] b] False True
[!a]] b True False
*[[][0-9a-f]] h[c True False

With the default options, Filter(["items[3]", "items[3", "notes.txt"], "*[[][0-9]]") returns only items[3. The excluded form -*[[][0-9]] keeps items[3], which it was written to hide.

Patterns where something else comes between the class and the ] are unaffected. For example, *[[]DEBUG]* matches x[DEBUG]y correctly.

Suggested fix / acceptance criteria

  • In ExpandGlobClasses, after a class closes at close, emit each ] that follows it as the one-member class []] instead of a bare ]. DotNet.Glob already reads []] correctly: a[]]b matches a]b. Tried on a local copy:
    • *[[][0-9][]] matches items[3] and not items[3
    • [a][]] matches a] and not a
    • [a][]][]] matches a]]
  • The shortcut if (!token.Contains(']')) return token; still holds, but a token that contains a class must go through this rewrite even when the class needs no list expansion.
  • Add tests for every row of the table under both case sensitivities, plus the Filter/excluded-token cases above.
  • Related: open PR Match an unclosed glob bracket literally [patch] #165 rewrites an unclosed [ as [[] in the same loop. This is the mirror case, a stray ] after a closed class, and it is not covered there.

Activity

  1. matt-edmondson commented on Oct 31, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

  2. added a commit that references this issue on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions