SD.
SD.

Reputation: 9559

Match exactly one of each from set of characters

I am trying to match a specific set of characters but 1 and only 1 of each.

For example if the set is [abcd], I want to match string containing these exact characters in any order.

abcd  - true
bcad  - true
abc   - false (need all characters)
abbd  - false
abcdd - false

From what I understand so far there is no easy way to achieve this with RegEx but no answer was conclusive enough.

Upvotes: 7

Views: 3213

Answers (5)

Michael come lately
Michael come lately

Reputation: 9422

See bobble bubble's excellent answer for a real regex solution (which is sometimes necessary). This answer uses sorting and string equality instead of a single regex:

var set = 'bcad'; // in any order
var tests = [
  'abcd',  // true
  'bcad',  // true
  'abc',   // false (need all characters)
  'abbd',  // false
  'abcdd', // false
];

var setSorted = set.split('').sort().join();

for (var i = 0; i < tests.length; i++) {
  var pass = setSorted == tests[i].split('').sort().join();
  console.log(`${tests[i]}: ${pass}`);
}

Upvotes: 1

JJoao
JJoao

Reputation: 5357

Just a humble contribution using grep:

grep -Px '[abcd]{4}' | grep -vP '(.).*\1'
  • get a seq of 4 [abcd]
  • and remove the lines contining repetitions

Upvotes: 1

bobble bubble
bobble bubble

Reputation: 18555

I would think of capturing and using a lookahead to check if the same character is not ahead.

\b(?:([abcd])(?!\w*?\1)){4}\b
  • (?: opens a non capture group for repetition
  • \b matches a word boundary
  • ([abcd]) captures one of [abcd]
  • (?!\w*?\1) checks if the captured character is not ahead with any amount of \w in between
  • {4}\b 4 times until another word boundary

See demo at regex101   (works only, if a lookahead is available in your regex flavor)

Upvotes: 9

Maroun
Maroun

Reputation: 96016

The problem you're trying to solve is checking whether a string is a permutation of "abcd".

You don't want to use regex for every problem you have. It's useful and powerful when you have a pattern. Checking if a string is a permutations of "abcd" is not really a "pattern".

The best approach would be using the language's power and construct a solution from the functions available for you.

Upvotes: 2

anubhava
anubhava

Reputation: 786291

You can use a lookahead for each character to assert that char is present only once in your regex.

So e.g. for your input chars abcd generate this regex:

^(?=[^a]*a[^a]*$)(?=[^b]*b[^b]*$)(?=[^c]*c[^c]*$)(?=[^d]*d[^d]*$)

RegEx Demo

^(?=[^a]*a[^a]*$) will assert that a is present only once in input. and so on for other chars b,c,d.

Upvotes: 2

Related Questions