Home > Software engineering >  Javascript regex to replace part of substring not working as expected?
Javascript regex to replace part of substring not working as expected?

Time:12-05

I'm working with times and meridiems.

I could have '2:0 a. m.' or '2:0 am' or '3:0 p. m.' or '3:0 pm' Basically what I'm trying to do is transform the first in the second when it happens.

My attempts:

console.info('2:0 a. m.'.replace(/(.*?\s)([ampAMP]*?)/, "$1")); // 2:0 a. m.

This one I really don't understand...

'2:0 a. m.'.replace(/(.*?\s)([ampAMP]).*?([ampAMP])/, "$1"); // 2:0 .

This one works but looks weird, not sure it's the best way

'2:0 a. m.'.replace(/(.*?\s)([ampAMP]).*?([ampAMP]).*?$/, "$1$2$3");

I was barely able to remove the meridiem from the time, but how can I replace all characters not matching [aAmMpP] just AFTER the first space?

CodePudding user response:

If you want to match am or pm, using [ampAMP] matches only a single character. If you use it twice, then you would allow for mm which is not a valid format.

You could make the pattern match more variations and capture what you want to keep. Then in the replacement use the capture groups to create the format that you want.

If the dots are mandatory:

\b(\d{1,2})\s*:\s*(\d{1,2})\s*([ap])\.\s*m\.
  • \b A word boundary
  • (\d{1,2}) Capture group 1, match 1-2 digits
  • \s*:\s* Math : between optional whitespace chars
  • (\d{1,2}) Capture group 2, match 1-2 digits
  • \s* Match optional whitespace chars
  • ([ap]) Capture group 3, match either a or b
  • \.\s*m\. Match . optional whitespace chars m and .

See a regex demo.

In the replacement use (as you already know that you have matched the m char)

$1:$2 $3m

const regex = /\b(\d{1,2})\s*:\s*(\d{1,2})\s*([ap])\.\s*m\./;
[
  "2:0 a. m.",
  "2:0 p. m.",
  "3:0 p. m.",
  "3:0p.m.",
  "2:0 am"
].forEach(s => console.log(s.replace(regex, "$1:$2 $3m")));

A bit more time like specific pattern, allowing an optional digit 0-5 for the seconds part:

\b([0-1]?[0-9]|2[0-3])\s*:\s*([0-5]?[0-9])\s*([ap])\.\s*m\.

Regex demo

CodePudding user response:

To replace the text "a. m." or "am" with "am" and the text "p. m." or "pm" with "pm" in a string, you can use the following regular expression:

/^(.?\s)(a.?\sm|p.?\s*m)/g

This regular expression will match the text "a. m." or "am" at the beginning of the string (indicated by the ^ character), after any number of characters followed by a space (indicated by the .*?\s pattern). It will also match the text "p. m." or "pm" in the same way.

To use this regular expression in the replace() method, you can pass it as the first argument, and "am" or "pm" as the second argument, depending on the matched text. For example:

'2:0 a. m.'.replace(/^(.?\s)(a.?\sm|p.?\s*m)/g, "$1am"); // returns "2:0 am"

'2:0 p. m.'.replace(/^(.?\s)(a.?\sm|p.?\s*m)/g, "$1pm"); // returns "2:0

EDIT

To replace the text "a. m." or "am" with "am" and the text "p. m." or "pm" dynamically, you can use a regular expression with a capturing group to match the "am" or "pm" part of the string, and then use the capturing group in the replacement string.

Here's an example regular expression that you can use:

/^(.?\s)(a.?\sm|p.?\s*m)/g

This regular expression will match the text "a. m." or "am" at the beginning of the string (indicated by the ^ character), after any number of characters followed by a space (indicated by the .*?\s pattern). It will also match the text "p. m." or "pm" in the same way. The part of the string that matches "am" or "pm" will be captured in the second capturing group (indicated by the parentheses around the second part of the regular expression).

To use this regular expression in the replace() method, you can use the $2 placeholder in the replacement string to refer to the second capturing group. For example:

'2:0 a. m.'.replace(/^(.?\s)(a.?\sm|p.?\s*m)/g, "$1$2"); // returns "2:0 am"

'2:0 p. m.'.replace(/^(.?\s)(a.?\sm|p.?\s*m)/g, "$1$2"); // returns "2:0 pm"

CodePudding user response:

For now after many attempts this works, alghough not very clean

let time = "02:00 p. m.";
time = time.replace(/(.*?\s)([ampAMP]).*?([ampAMP]).*?$/, "$1$2$3");
console.log(time);

with the selected answer I had

let time = "02:00 a. m.";
time = time.replace(/\b(\d{1,2})\s*:\s*(\d{1,2})\s*([ap])\.\s*m\./i, "$1:$2 $3m");
console.log(time);

but by the way I ended up doing this:

let time = "02:00 a. m.";
time = time .replace(/\.\s*/g, "");
console.log(time);

because although it was good, I had performance issues.

hope it helps

CodePudding user response:

If I understood correctly by first in the second, this should work.

const regex = /^([^\s]\s)([^aAmMpP])/;
const string = '2:0 a. m.';
const result = string.replace(regex, '$1am');

console.log(result); // Output: '2:0 am'

regex using the " /^([^\s]\s)([^aAmMpP])/"

  • Related