cliffycheng
cliffycheng

Reputation: 381

Regex for no duplicate characters from a limited character pool

Is there a way to write a regex to match a string that only contains certain characters, and never repeats those characters? I already wrote some code using a set to implement this, but would like to know if there's a regex way to do it.

So for example, if I only wanted a string that contains [A,B,C], and I want to match to a string that never duplicates any of those characters, eg A, B, C, AB, AC, B, BC, ABC, and so on, but never matches AA, BB, CC, etc

Thanks!

Upvotes: 14

Views: 15510

Answers (3)

user12097764
user12097764

Reputation:

I'm answering this question

Visual C++ Regex: Matching no repeating letter

which was marked an exact duplicate of this question.

No repeating of any letter ?
Does that mean consecutive letters, or is abaca ok ?

if not, the regex would be yours modified to this :

^(?=.*[a-z])(?!.*([a-z]).*\1).{4,20}$

Expanded

 ^ 
 (?= .* [a-z] )
 (?!
      .* 
      ( [a-z] )                     # (1)
      .* \1 
 )
 .{4,20} 
 $ 

Upvotes: 2

hek2mgl
hek2mgl

Reputation: 157990

back referencing can be used. Here comes an example in PHP, which is compatible to Perl regular expressions:

$string = "A, B, C, AB, AC, B, BC, AABC";

if(preg_match('/([ABC])\1/', $string, $matches)) {
    echo $matches[1] . " has been repeated\n";
} else {
    echo "OK\n";
}

In the above pattern ([ABC]) is capturing group which can store one out of the characters A, B or C. \1 references this first capturing group, this makes the pattern matching if one those characters repeats.

Upvotes: 2

Tim Pietzcker
Tim Pietzcker

Reputation: 336158

That's easy to do with a negative lookahead assertion:

^(?!.*(.).*\1)[ABC]+$

matches exactly as you described.

Test it live on regex101.com.

Explanation:

^      # Start of the string
(?!    # Assert that it's impossible to match...
 .*    # Any number of characters (including zero)
 (.)   # followed by one character (remember this one in group 1)
 .*    # that's followed by any number of characters
 \1    # and the same character as before
)      # End of lookahead
[ABC]+ # Match one or more characters from this list
$      # until the end of the string

Upvotes: 21

Related Questions