0
votes

I'm trying to match a string which is only valid if all characters after the first occurrence of the target character, are also the the target character.

To better understand the structure, for example our target character is .. The string is divided into two parts. The matching string has the following structure:

  1. substring without the target character
  2. substring with no other characters than the target character

Let's examine some examples:

""
// true - 1: "" doesn't contain target - 2: "" doesn't contain not target

"2"
// true - 1: "2" doesn't contain target - 2: "" doesn't contain not target

"."
// true - 1: "" doesn't contain target - 2: "." doesn't contain not target (only target)

"2.."
// true - 1: "2" doesn't contain target - 2: ".." doesn't contain not target (only target)

"...."
// true - 1: "" doesn't contain target - 2: "...." doesn't contain not target (only target)

"..2"
// false - 1: "..2" contains target - 2: "" doesn't contain not target

"2.2"
// false - 1: "2.2" contains target - 2: "" doesn't contain not target

"2.2."
// false - 1: "2.2" contains target - 2: "." doesn't contain not target (only target)

I was approaching the problem first with String methods (JS) by checking index of first occurrence, then counting number of occurrences, comparing with the length of string to check if there are any other characters between the ending, which was solving the problem, but wasn't looking too nice, and I don't think it's the most efficient way to solve the issue.

It looks like this:

const validate = (string, targetChar) => {
  const firstTargetIndex = string.indexOf(targetChar);
  if (firstTargetIndex === -1) return true; //no chance of not target following a target

  const substringAfterFirstTarget = string.substr(firstTargetIndex);
  const numberOfTargets = substringAfterFirstTarget.split(targetChar).length - 1;
  return substringAfterFirstTarget.length === numberOfTargets;
}

Then I was researching regex methods to solve the problem, but I only found methods for checking occurrence, number of occurrence, if string ends with (even n times, but ignoring if there are occurrences between other characters), but couldn't figure a method to match the above test.

3
please make an attempt before askingdepperm
You want to know my search history or my failed attempts? How would the results I've found not solving the issue help anyone?Gergő Horváth
And you may be way closer to the solution than you expectCid
is this javascript or some other language? do you need to use regex alone or can you use other logic?depperm
Is this a valid rewording? "All characters after the first occurrence of the specified character, must also be the specified character."Wyck

3 Answers

2
votes

The regex ^[^.]*\.*$ should work. It can accept any none . character 0 or more times ([^.]*) and then it can be followed by any number of . (\.*)

const regex = /^[^.]*\.*$/gm;
const str = ['','2','.','2..','....','..2','2.2','2.2.'];

console.log(str.map(s=>s.match(regex)?'true':'false'))

// example from comments does return false
console.log(regex.test('..2.'))
0
votes
  1. Case where dot is not in string: ^[\.]*$
  2. Case where dot ends the string: \.$

Put them together with alternation, you get dot at end or not at all

(\.$)|(^[\.]*$)
0
votes

In English: match if it is zero or more non-dot chars followed by zero or more dot chars:

Mac_3.2.57$cat test.txt | egrep "^[^.]*\.*$"
2
.
2..
....

x

Mac_3.2.57$cat test.txt

2
.
2..
....
..2
2.2
2.2.

x
Mac_3.2.57$

PS The previous answer did not work for me:

> const str = ['','2','.','2..','....','..2','2.2','2.2.'];
Uncaught SyntaxError: Identifier 'str' has already been declared
> console.log(str.map(s=>s.match(regex)?'true':'false'))
[
  'true',  'true',
  'true',  'true',
  'true',  'false',
  'false', 'false'
]
undefined
> const str = ['','2','.','2..','..2.','..2','2.2','2.2.'];
Uncaught SyntaxError: Identifier 'str' has already been declared
> console.log(str.map(s=>s.match(regex)?'true':'false'))
[
  'true',  'true',
  'true',  'true',
  'true',  'false',
  'false', 'false'
]
undefined
>