Extract text between last slash and last dot using regex - javascript

I have string like this in javascript
at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/logger.service.ts:107:29)
I want to extract logger.service from it. the formula is between last / to last .
I can extract from last / using /([^\/]+$)/g but don't know how to limit the finding to last .
Note: these are other examples:
at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/logger.ts:107:29)
expected: logger
at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/logger.js:107:29)
expected: logger
at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/api.logger.service.ts:107:29)
expected: api.logger.service

You can use
/.*\/(.*)\./
Details:
.* - any zero or more chars other than line break chars as many as possible
\/ - a / char
(.*) - Group 1: any zero or more chars other than line break chars as many as possible
\. - a . char.
See the JavaScript demo:
const text = "at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/api.logger.service.ts:107:29)";
const match = text.match(/.*\/(.*)\./)
if (match) {
console.log(match[1]);
}

We can try using a regex replacement approach here:
var log = "at LoggerService.log (/Users/apps/api/webpack:/pcs-goc-api/pcs-libs/logger/src/api.logger.service.ts:107:29)";
var output = log.replace(/^.*\/|\.[^.]*$/g, "");
console.log(output);
The regex pattern here says to match:
^.*\/ all content from the start up to and including the LAST /
| OR
\.[^.]*$ all content from the LAST dot until the end
Then, we replace with empty string, leaving behind the string we want.

([^\/]+)[.][^:]+:\d+:\d+
Demo: https://regex101.com/r/FeLRmi/1
[.] => "." character
[^:] => Any character except ":"
[^:]+ => One or more [^:]
:\d+ => One or more digits after ":"
All the other regex statements are your own.

Related

How to format a JavaScript string with replaceAll using regex

I am trying to format a kind of a board game notation which consists of tabs and spaces.
The original string is looking like this:
1. \td11-d9 \te7-e10 \n2. \ta8-c8 \tg7-g10xf10 \n3. \th11-h9 \tf7-i7
I used this replace method to clean up all of the tabs and new lines
string.replace(/\s\s+/g, ' ').replaceAll('. ', '.');
So, after that the string is looking like this:
1.d11-d9 e7-e10 2.a8-c8 g7-g10xf10 3.h11-h9 f7-i7
However, I want to add more space before the number with the dot. So, the string must look like this with 3 spaces before the number of the move (the number with the dot):
1.d11-d9 e7-e10 2.a8-c8 g7-g10xf10 3.h11-h9 f7-i7
Can I also make all of these operations with a one line code or just one JavaScript method?
Here is how you can do this in a single .replace call:
const s = "1. \td11-d9 \te7-e10 \n2. \ta8-c8 \tg7-g10xf10 \n3. \th11-h9 \tf7-i7 ";
var r = s.replace(/([.\s])\s*\t|\s+$|\n(?=\d\.)/g, '$1');
console.log(r);
//=> "1.d11-d9 e7-e10 2.a8-c8 g7-g10xf10 3.h11-h9 f7-i7"
RegEx Breakup:
([.\s])\s*\t: Match dot or a whitespace and capture in group #1 followed by 0+ whitespaces followed by a tab. We will put back this replacement using $1
|: OR
\s+$: Match 1+ whitespaces before end
|: OR
\n(?=\d\.): Match \n if it is followed by a digit and a dot
You can use lookahead with (?=[1-9]) and (?=[a-z]) to check if the number add two spaces, and if a letter just add one space.
const string = `1. \td11-d9 \te7-e10 \n2. \ta8-c8 \tg7-g10xf10 \n3. \th11-h9 \tf7-i7`
const result = string.replace(/\s+(?=[a-z])/gi, ' ').replace(/\s+(?=[1-9])/gi, ' ').replaceAll('. ', '.');
console.log(result)

Regex Capture Character and Replace with another

Trying to replace the special characters preceded by digits with dot.
const time = "17:34:12:p. m.";
const output = time.replace(/\d+(.)/g, '.');
// Expected Output "17.34.12.p. m."
console.log(output);
I had wrote the regex which will capture any character preceded by digit/s. The output is replacing the digit too with the replacement. Can someone please help me to figure out the issue?
You can use
const time = "17:34:12:p. m.";
const output = time.replace(/(\d)[\W_]/g, '$1.');
console.log(output);
The time.replace(/(\d)[\W_]/g, '$1.') code will match and capture a digit into Group 1 and match any non-word or underscore chars, and the $1. replacement will put the digit back and replace : with ..
If you want to "subtract" whitespace pattern from [\W_], use (?:[^\w\s]|_).
Consider checking more special character patterns in Check for special characters in string.
You should look for non word(\w) and non spaces (\s) characters and replace them with dot.
You should use some live simulator for regular expressions. For example regex101: https://regex101.com/r/xIStHH/1
const time = "17:34:12:p. m.";
const output = time.replace(/[^\w\s]/g, '.');
// Expected Output "17.34.12.p. m."
console.log(output);

Javascript print some characters after regex match

Input string is "F000668A - EED14F50 - 000EED1KFF0000000F03".
I want to print/save 4 characters after EED1. The number of EED1 can 1 or more.
In the above example, the expected result is => 4F50,KFF0.
My code:
var input = "F000668A - EED14F50 - 000EED1kFF0000000F03"
const string = input.toLowerCase().replace(/\s/g, '').replace(/(\r\n|\n|\r)/gm, ""); //Lowercase it, delete spaces and linebreaks.
string.match(/eed1/g).forEach((element) => {
console.log(element)
});
Result:
eed1
eed1
But when I try to print further characters then the script print only 1 item.
string.match(/eed1(.*)/g)
Result:
eed14f50-000eed1kff0000000f03
How can I get the requested info with regex? (or an other way)
Thank you in advance.
You can use
const input = "F000668A - EED14F50 - 000EED1kFF0000000F03";
const matches = input.replace(/\s/g, '').matchAll(/eed1([a-z0-9]{4})/ig);
console.log(Array.from(matches, m => m[1]));
Note:
You do not need to replace line breaks separately from other whitespaces, \s matches \n, \r, and the rest of vertical whitesapce
There is no need to lowercase the input, you can use /i flag to match in a case insensitive way
/eed1([a-z0-9]{4})/ig will match all occurrences of eed1 (case insensitively) and then capture four letters/digits, and matchAll will ensure the access to all the capturing group values (match() discarded them all as the regex was built with the g flag).
See the regex demo.

Regex to detect dates separated by newlines

I'm trying to validate text that's in the format of dates separated by newlines.
The date format needs to be in the form of MM-DD-YYYY.
So a sample could be
MM-DD-YYYY\n
MM-DD-YYYY\n
MM-DD-YYYY
Where there could be an infinite amount of dates entered that are separated by newlines
I've tried /^(\d{2})-(\d{2})-(\d{4})\s+$/ but that doesn't seem to fully work.
Note: I want this to allow for any leading, trailing whitespace and empty newlines as well.
Basically,
A space character
A carriage return character
A newline character
I'm not partial to using regexes. If another way is simpler, desired, more efficient, than I'd gladly switch to that. Thanks!
To validate a string with multiple date-like strings in it with or without leading/trailing whitespace, allowing empty/blank lines, you may use
A method to split the text into lines and use .every() to test each line against a simple pattern:
text.split("\n").every(x => /^\s*(?:\d{2}-\d{2}-\d{4}\s*)?$/.test(x))
NOTE: This will validate a blank input!
Details
^ - start of string
\s* - 0+ whitespaces
(?: - starts a non-capturing group
\d{2}-\d{2}-\d{4} - two digits, -, two digits, - and four digits
\s* - 0+ whitespaces
)? - end of the group, repeat 1 or 0 times (it is optional)
$ - end of string.
A single regex for the multiline string
/^\s*\d{2}-\d{2}-\d{4}(?:[^\S\n]*\n\s*\d{2}-\d{2}-\d{4})*\s*$/.test(text)
See the regex demo. This will not validate blank input.
This regex is long, but is still efficient since the backtracking is minimal (see [^\S\n]*\n\s* part where the first [^\S\n]* matches any whitespace but a line feed, then \n matches a newline (hence, no backtracking here) and then \s* matches 0+ whitespace (again, \n is not quantified so no backtracking into the pattern is \s* fails). The (?:[^\S\n]*\n\s*\d{2}-\d{2}-\d{4})* part is a * quantified non-capturing group that matches 0 or more occurrences of the quantified pattern sequence.
JS demos:
var matching_text = "\n01-01-2020\n 01-01-2020\n01-01-2020 \n\n\n 01-01-2020 \n";
var non_matching_text = "\n01-01-2020\n 01-01-2020\n01-01-2020 \n\n\n 01-01-2020 \n01201-01-20202020";
var regex_1 = /^\s*(?:\d{2}-\d{2}-\d{4}\s*)?$/;
var regex_2 = /^\s*\d{2}-\d{2}-\d{4}(?:[^\S\n]*\n\s*\d{2}-\d{2}-\d{4})*\s*$/;
// Test Solution 1:
console.log(matching_text.split("\n").every(x => regex_1.test(x))); // => true
console.log(non_matching_text.split("\n").every(x => regex_1.test(x))); // => false
// Test Solution 2:
console.log(regex_2.test(matching_text)); // => true
console.log(regex_2.test(non_matching_text)); // => false
You can use something like below to get all matches that satisfy the regular expression. Notice the parentheses () are only around the date part (\d{2}-\d{2}-\d{4}) so that is what you will end up capturing. Since the global flag g is also set on the regex, this will return all occurrences of the parenthesized expression.
Edit: added support for a leading and trailing whitespace.
Edit 2: added ^ and $ so the regex doesn't allow for more than 2 digits in day and more than 4 digits in year.
Run and test:
let regex = /[\\s]*(\d{2}-\d{2}-\d{4})[\\s]*[\\n]*/g;
let dates = " 12-02-2020 \n 09-10-2020\n 03-03-2020 ";
console.log( dates.match(regex) );
EDIT: In order to validate the string of dates you could use the regex.test() method like this:
let regex = /^\s*\d{2}-\d{2}-\d{4}\s*$/;
let dateString = " 12-02-2020 \n 09-10-2020\n 03-03-2020 ";
var dates = dateString.split('\n');
var datesValid = () => {
dates.forEach((el) => {
if(!regex.test(el))
return false;
});
return true;
};
console.log( datesValid() );

Conditional regex replace in nodejs

I have an address like this:
117042,ABC DEF,HIJ KLMNOP,9,170
and want to have
117042,ABC DEF,HIJ KLMNOP 9 170
I tried it with this replace Regex
address = address.replace(/,[\d]/g, " ");
but this results in
117042,ABC DEF,HIJ KLMNOP 70
I do not want to replace the digit but still need to check if the digit comes after the comma to not match the other commas.
I am not very good with regex thats why I am asking for help.
You may only replace commas after numbers if they occur at the end of string:
var s = "117042,ABC DEF,HIJ KLMNOP,9,170";
var res = s.replace(/,(\d+)(?=(?:,\d+)*$)/g, " $1");
console.log(res);
The ,(\d+)(?=(?:,\d+)*$) regex matches:
, - a comma
(\d+) - (Group 1, referred to via $1 from the replacement pattern) one or more digits
(?=(?:,\d+)*$) - a positive lookahead that requires 0+ sequences of , + one or more digits at the end of the string.

Categories