Best way to manipulate and cut a string using character matching? - javascript

So in my example, we have strings that look like this:
CP1_ctl05_RCBPAThursdayStartTimePicker_0_dateInput
CP1_ctl05_RCBPAFridayStartTimePicker_3_dateInput
CP1_ctl05_RCBPAMondayStartTimePicker_1_dateInput
The task is to extract the days of the week from the string.
I already figured you can trim the first set of characters CP1_ctl05_RCBPA as they will always have the same length and will always occur in the same position. Using string.substr(15), I was able to reduce the string to FridayStartTimePicker_3_dateInput but I am not sure how to approach deleting the rest of the suffixal garbage text.
I was thinking about trimming the end by finding the first occurring y (as it will only occur in days of the week in this case) and slicing off the end up until that point, but I am not sure about how to approach slicing off a part of a string like this.

You can use regex to extract them. As every day ends with a y, and no day has a y in between, you can simply use that as delimiter
const regex = /\w{15}(\w+y).*/g;
const str = `CP1_ctl05_RCBPAThursdayStartTimePicker_0_dateInput`;
const subst = `\$1`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
console.log('Substitution result: ', result);

Instead of deleting unwanted parts, you could just match what you want.
The following regex ^.{15}(\w+?y) matches 15 any character from the begining of the string then matches and capture in group 1 one or more word character not greedy then the letter y. It is mandatory to use not greedy ? unless it will match until the last y that exists in the string.
We then just have to get the content of the first group and assign to variable day
var test = [
'CP1_ctl05_RCBPAThursdayStartTimePicker_0_dateInput', 'CP1_ctl05_RCBPAFridayStartTimePicker_3_dateInput', 'CP1_ctl05_RCBPAMondayStartTimePicker_1_dateInput'
];
console.log(test.map(function (a) {
return a.match(/^.{15}(\w+?y)/)[1]
}));

Related

JS split string on positive lookahead, avoid overlapping cases

I have a set of data that includes dated notes, all concatenated, as in the example below. Assume the date always comes at the beginning of its note. I'd like to split these into individual notes. I've used a positive lookahead so I can keep the delimiter (the date).
Here's what I'm doing:
const notes = "[3/28- A note. 3/25- Another note. 3/24- More text. 10/19- further notes. [10/18- Some more text.]"
const pattern = /(?=\d{1,2}\/\d{1,2}[- ]+)/g
console.log(notes.split(pattern))
and the result is
[ '[',
'3/28- A note. ',
'3/25- Another note. ',
'3/24- More text. ',
'1',
'0/19- further notes. [',
'1',
'0/18- Some more text.]' ]
The pattern \d{1,2} matches both 10/19 and 0/19 so it splits before both of those.
Instead I'd like to have
[ '[',
'3/28- A note. ',
'3/25- Another note. ',
'3/24- More text. ',
'10/19- further notes. [',
'10/18- Some more text.]' ]
(I can handle the extraneous brackets later.)
How can I accomplish this split with regex or any other technique?
To get your wanted output, you can prepend a word boundary in the lookahead, and you can omit the plus sign at the end of the pattern.
(?=\b\d{1,2}\/\d{1,2}[- ])
Regex demo
const notes = "[3/28- A note. 3/25- Another note. 3/24- More text. 10/19- further notes. [10/18- Some more text.]"
const pattern = /(?=\b\d{1,2}\/\d{1,2}[- ])/g
console.log(notes.split(pattern))
I would avoid split() here and instead use match():
var notes = "[3/28- A note. 3/25- Another note. 3/24- More text. 10/19- further notes. [10/18- Some more text.]";
var matches = notes.match(/\[?\d+\/\d+\s*-\s*.*?\.\]?/g);
console.log(matches);
You may do a further cleanup of leading/trailing brackets using regex, e.g.
var input = "[10/18- Some more text.]";
var output = input.replace(/^\[|\]$/, "");
Try .replaceAll() and this regex:
/(\[?\d{1,2}\/\d{1,2}\-.+?)/
// Replacement
"\n$1"
Figure I - Regex
Segment
Description
(\[?
Begin capture group - match literal "[" zero or one time
\d{1,2}\/
match a digit one or two times and a literal "/"
\d{1,2}\-
match a digit one or two times and a literal "-"
.+?)
match anything one to any number of times "lazily" - end capture group
Figure II - Replacement
Segment
Description
\n
New line
$1
Everything matched in the capture group (...)
const notes = "[3/28- A note. 3/25- Another note 3/24- More text. 10/19- further notes [10/18- Some more text.]";
const rgx = new RegExp(/(\[?\d{1,2}\/\d{1,2}\-.+?)/, 'g');
let result = notes.replaceAll(rgx, "\n$1");
console.log(result);

regex with replace() for letters only

I have a string that output
20153 Risk
What i am trying to achieve is getting only letters, i have achieved by getting only numbers using regular expression which is
const cf_regex_number = cf_input.replace(/\D/g, '');
this will return only 20153 . But as soon as i tried to only get letters , its returning the while string instead of Risk . i have done my research and the regular expression to get only letters is using **/^[a-zA-Z]*$/**
This is my line of code i tried to get only letters
const cf_regex_character = cf_input.replace(/^[a-zA-Z]*$/,'')
but instead of returning Risk , it is returning 20153 Risk which is the whole line of string .
/[^a-z]+/i
The [ brackets ] signify a range of characters; specifically, a to z in this case.
Actually the i flag means insensitive to case, so that includes A to Z also.
The caret ^ inverts the pattern; it means, anything not in the specified range.
And the + means continue adding characters to the match as long as they are they within that range.
Then stop matching.
In effect this matches everything up to the space in 20153 Risk.
Then you replace this match with the empty string '' and what you've got left is Risk.
const string = '20153 Risk';
const result = string.replace(/[^a-z]+/i, '');
console.log(result);
Your first pattern is locating every non-digit and replacing it with nothing.
On the other hand, your second pattern is locating just the first occurence of a pattern, and the pattern is looking for start of string, followed by letters, followed by end of string. There is no such sequence - if you start from the start of string, there are exactly zero letters, and then you are left very far from the expected end of the string. Even if that worked, you are deleting letters, not non-letters.
This pattern is parallel to your first one (delete any occurence of a non-letter):
const cf_regex_character = cf_input.replace(/[^a-zA-Z]/g,'')
but possibly a better way to go is to extract the desired substring, instead of deleting everything that it is not:
const letters = cf_input.match(/[a-z]+/i)[0];
const numbers = cf_input.match(/\d+/)[0];
(This is if you know there is such a substring; if you are unsure it would be better to code a bit more defensively.)
cf_input="20153 Risk"
const cf_regex_character = cf_input.replace(/\d+\s/,'')
console.log(cf_regex_character)
str="20153 Risk"
reg=/[a-z]+/gi
res=str.match(reg)
console.log(res[0])

Add a space to UK Postcode in correct place Javascript

I am trying to write a basic function that will allow me to add a space to UK postcodes where the spaces have been removed.
UK postcodes always have a space before the final digit of the postcode string.
Some examples with no spacing and with correct spacing:
CB30QB => CB3 0QB
N12NL => N1 2NL
OX144FB => OX14 4FB
To find the final digit in the string I am regex /\d(?=\D*$)/g and the Javascript I have in place currently is as follows:
// Set the Postcode
var postCode = "OX144FB";
// Find the index position of the final digit in the string (in this case '4')
var postcodeIndex = postCode.indexOf(postCode.match(/\d(?=\D*$)/g));
// Slice the final postcode at the index point, add a space and join back together.
var finalPostcode = [postCode.slice(0, postcodeIndex), ' ', postCode.slice(postcodeIndex)].join('');
return finalPostcode;
I am getting the following results when I change the set postcost:
CB30QB becomes CB3 0QB - Correct
N12NL becomes N1 2NL - Correct
CB249LQ becomes CB24 9LQ - Correct
OX144FB becomes OX1 44FB - Incorrect
OX145FB becomes OX14 5FB - Correct
It seems that the issue might be to do with having two digits of the same value as most other combinations seem to work.
Does anyone know how I can fix this?
I should use string.replace
string.replace(/^(.*)(\d)/, "$1 $2");
DEMO
You can use replace() with regex, you need to place space before 3 letters from the end
document.write('CB30QB'.replace(/^(.*)(.{3})$/,'$1 $2')+'<br>');
document.write('N12NL'.replace(/^(.*)(.{3})$/,'$1 $2')+'<br>');
document.write('CB249LQ'.replace(/^(.*)(.{3})$/,'$1 $2')+'<br>');
document.write('OX144FB'.replace(/^(.*)(.{3})$/,'$1 $2'));
As everyone else is answering, .replace() is easier. However, let me point what's wrong in the code.
The problem is you're using postCode.indexOf() to find the first occurence of what has been matched. In this case:
Text: OX144FB
Match: ^ match is correct: "4"
Text: OX144FB
IndexOf: ^ first occurence of "4"
To fix it, use the .index of the match object:
// Find the index position of the final digit in the string (in this case '4')
var postcodeIndex = postCode.match(/\d(?=\D*$)/g).index;
var postCode = "OX144FB";
return postCode.replace(/^(.*)(\d)(.*)/, "$1 $2$3");
Using the String.prototype.replace method is obviously the easiest way:
return postCode.replace(/(?=\d\D*$)/, ' ');
or using the greediness:
return postCode.replace(/^(.*)(?=\d)/, '$1 ');
Your previous code doesn't work because you are searching with indexOf the substring matched with the String.prototype.match() method (that is the last digit before the end). But if this digit is several times in the string, indexOf will return the position of the first occurrence.
As an aside, when you want to find the position of a match in a string, use the String.prototype.search() method that returns this position.
This is an old problem, but whilst Avinash Raj's solution works, it only works if all your postcodes are without spaces. If you have a mix, and you want to regularize them to having a single space, you can use this regex:
string.replace(/(\S*)\s*(\d)/, "$1 $2");
DEMO - it even works with more than one space!

Javascript regex match returning a string with comma at the end

Just as the title says...i'm trying to parse a string for example
2x + 3y
and i'm trying to get only the coefficients (i.e. 2 and 3)
I first tokenized it with space character as delimiter giving me "2x" "+" "3y"
then i parsed it again to this statement to get only the coefficients
var number = eqTokens[i].match(/(\-)?\d+/);
I tried printing the output but it gave me "2,"
why is it printing like this and how do i fix it? i tried using:
number = number.replace(/[,]/, "");
but this just gives me an error that number.replace is not a function
What's wrong with this?
> "2x + 3y".match(/-?\d+(?=[A-Za-z]+)/g)
[ '2', '3' ]
The above regex would match the numbers only if it's followed by one or more alphabets.
Match is going to return an array of every match. Since you put the optional negative in a parentheses, it's another capture group. That capture group has one term and it's optional, so it'll return an empty match in addition to your actual match.
Input 2x -> Your output: [2,undefined] which prints out as "2,"
Input -2x -> Your output: [2,-]
Remove the parentheses around the negative.
This is just for the sake of explaining why your case is breaking but personally I'd use Avinash's answer.

capture with regex in javascript

I have a string like "ListUI_col_order[01234567][5]". I'd like to capture the two numeric sequences from the string. The last part between the square brackets may contain 2 digits, while the first numeric sequence always contains 8 digits (And the numbers are dynamically changing of course.) Im doing this in javascript and the code for the first part is simple: I get the only 8digit sequence from the string:
var str = $(this).attr('id');
var unique = str.match(/([0-9]){8}/g);
Getting the second part is a bit complicated to me. I cannot simply use:
var column = str.match(/[0-9]{1,2}/g)
Because this will match '01', '23', '45', '67', '5' in our example, It's clear. Although I'm able to get the information what I need as column[4], because the first part always contains 8 digits, but I'd like a nicer way to retrieve the last number.
So I define the contex and I can tell the regex that Im looking for a 1 or 2 digit number which has square brackets directly before and after it:
var column = str.match(/\[[0-9]{1,2}\]/g)
// this will return [5]. which is nearly what I want
So to get Only the numeric data I use parenthesis to capture only the numbers like:
var column = str.match(/\[([0-9]){1,2}\]/g)
// this will result in:
// column[0] = '[5]'
// column[1] = [5]
So my question is how to match the '[5]' but only capture the '5'? I have only the [0-9] between the parenthesis, but this will still capture the square brackets as well
You can get both numbers in one go :
var m = str.match(/\[(\d{8})\]\[(\d{1,2})\]$/)
For your example, this makes ["[01234567][5]", "01234567", "5"]
To get both matches as numbers, you can then do
if (m) return m.slice(1).map(Number)
which builds [1234567, 5]
Unfortunately, JavaScript does not support the lookbehind necessary to do this. In other languages such as PHP, it'd be as simple as /(?<=\[)\d{1,2}(?=\])/, but in JavaScript I am not aware of any way to do this other than use a capturing subpattern as you are here, and getting that index from the result array.
Side-note, it's usually better to put the quantifier inside the capturing group - otherwise you're repeating the group itself, not its contents!

Categories