Replace last character of a matched string using regex - javascript

I am need to post-process lines in a file by replacing the last character of string matching a certain pattern.
The string in question is:
BRDA:2,1,0,0
I'd like to replace the last digit from 0 to 1. The second and third digits are variable, but the string will always start BRDA:2 that I want to affect.
I know I can match the entire string using regex like so
/BRDA:2,\d,\d,1
How would I get at that last digit for performing a replace on?
Thanks

You may match and capture the parts of the string with capturing groups to be able to restore those parts in the replacement result later with backreferences. What you need to replace/remove should be just matched.
So, use
var s = "BRDA:2,1,0,0"
s = s.replace(/(BRDA:2,\d+,\d+,)\d+/, "$11")
console.log(s)
If you need to match the whole string you also need to wrap the pattern with ^ and $:
s = s.replace(/^(BRDA:2,\d+,\d+,)\d+$/, "$11")
Details:
^ - a start of string anchor
(BRDA:2,\d+,\d+,) - Capturing group #1 matching:
BRDA:2, - a literal sunstring BRDA:2,
\d+ - 1 or more digits
, - a comma
\d+, - 1+ digits and a comma
\d+ - 1+ digits.
The replacement - $11 - is parsed by the JS regex engine as the $1 backreference to the value kept inside Group 1 and a 1 digit.

Related

Adding zero to non leaded zero datetime string regex

I have the following datetime string 2020-5-1 1:2 I used the pattern (\W)(\d{1}) to match any digit with length 1 i.e non zero leaded, 5,1,1,2. This demo shows that pattern succeeded to catch them in the group 2 for every match.
Using Javascript's String replace method, I have tried to turn the datetime sample string to be 2020-05-01 01:02. In this jsbin that runs the following snippet:
var txt = '2020-5-1 1:2'
var output = [];
output[0] = txt.replace(/(\W)(\d{1})/gi,'0$1');
output[1] = txt.replace(/(\W)(\d{1})/gi,'0$2');
console.log(output);
// The output: ["20200-0-0 0:", "202005010102"]
In the first output's entry, it does unexpected behavior, instead of adding 0 to the match, it replaced it with 0! How could I solve this issue?
You only used a single placeholder in the replacement pattern, but in the regex pattern, you consumed two substrings with two capturing groups, so one is lost.
To add 0 before single digits you may use
txt.replace(/\b\d\b/g,'0$&')
txt.replace(/(^|\D)(\d)(?!\d)/g,'$10$2')
txt.replace(/(?<!\d)\d(?!\d)/g,'0$&') // With the ECMAScript2018+
Here, \b\d\b matches a digit that is neither preceded nor followed with an ASCII letter, digit or _. The substitution is 0 and the whole match value, $&.
The (^|\D)(\d)(?!\d) pattern capture start of string or a non-digit char into Group 1, then a digit is captured in Group 2. Then, (?!\d) makes sure there is no digit immediately to the right. The substitution is $10$2, Group 1 value, 0 and then Group 2 value.
The (?<!\d)\d(?!\d) pattern matches any digit not enclosed with other digits, and the substitution is the same as in Case 1.
JS demo:
var txt = '2020-5-1 1:2';
console.log( txt.replace(/\b\d\b/g,'0$&') )
console.log( txt.replace(/(^|\D)(\d)(?!\d)/g,'$10$2') )

Regex match multiple same expression multiple times

I have got this string {bgRed Please run a task, {red a list has been provided below}, I need to do a string replace to remove the braces and also the first word.
So below I would want to remove {bgRed and {red and then the trailing brace which I can do separate.
I have managed to create this regex, but it is only matching {bgRed and not {red, can someone lend a hand?
/^\{.+?(?=\s)/gm
Note you are using ^ anchor at the start and that makes your pattern only match at the start of a line (mind also the m modifier). .+?(?=\s|$) is too cumbersome, you want to match any 1+ chars up to the first whitespace or end of string, use {\S+ (or {\S* if you plan to match { without any non-whitespace chars after it).
You may use
s = s.replace(/{\S*|}/g, '')
You may trim the outcome to get rid of resulting leading/trailing spaces:
s = s.replace(/{\S*|}/g, '').trim()
See the regex demo and the regex graph:
Details
{\S* - { char followed with 0 or more non-whitespace characters
| - or
} - a } char.
If the goal is go to from
"{bgRed Please run a task, {red a list has been provided below}"
to
"Please run a task, a list has been provided below"
a regex with two capture groups seems simplest:
const original = "{bgRed Please run a task, {red a list has been provided below}";
const rex = /\{\w+ ([^{]+)\{\w+ ([^}]+)}/g;
const result = original.replace(rex, "$1$2");
console.log(result);
\{\w+ ([^{]+)\{\w+ ([^}]+)} is:
\{ - a literal {
\w+ - one or more word characters ("bgRed")
a literal space
([^{]+) one or more characters that aren't {, captured to group 1
\{ - another literal {
\w+ - one or more word characters ("red")
([^}]+) - one or more characters that aren't }, captured to group 2
} - a literal }
The replacement uses $1 and $2 to swap in the capture group contents.

“combine” 2 regex with a logic or?

I have two patterns for javascript:
/^[A-z0-9]{10}$/ - string of exactly length of 10 of alphanumeric symbols.
and
/^\d+$/ - any number of at least length of one.
How to make the expression of OR string of 10 or any number?
var pattern = /^([A-z0-9]{10})|(\d+)$/;
doesn't work by some reason. It passes at lest
pattern.test("123kjhkjhkj33f"); // true
which is not number and not of length of 10 for A-z0-9 string.
Note that your ^([A-z0-9]{10})|(\d+)$ pattern matches 10 chars from the A-z0-9 ranges at the start of the string (the ^ only modifies the ([A-z0-9]{10}) part (the first alternative branch), or (|) 1 or more digits at the end of the stirng with (\d+)$ (the $ only modifies the (\d+) branch pattern.
Also note that the A-z is a typo, [A-z] does not only match ASCII letters.
You need to fix it as follows:
var pattern = /^(?:[A-Za-z0-9]{10}|\d+)$/;
or with the i modifier:
var pattern = /^(?:[a-z0-9]{10}|\d+)$/i;
See the regex demo.
Note that grouping is important here: the (?:...|...) makes the anchors apply to each of them appropriately.
Details
^ - start of string
(?: - a non-capturing alternation group:
[A-Za-z0-9]{10} - 10 alphanumeric chars
| - or
\d+ - 1 or more digits
) - end of the grouping construct
$ - end of string

Why isn't this group capturing all items that appear in parentheses?

I'm trying to create a regex that will capture a string not enclosed by parentheses in the first group, followed by any amount of strings enclosed by parentheses.
e.g.
2(3)(4)(5)
Should be: 2 - first group, 3 - second group, and so on.
What I came up with is this regex: (I'm using JavaScript)
([^()]*)(?:\((([^)]*))\))*
However, when I enter a string like A(B)(C)(D), I only get the A and D captured.
https://regex101.com/r/HQC0ib/1
Can anyone help me out on this, and possibly explain where the error is?
Since you cannot use a \G anchor in JS regex (to match consecutive matches), and there is no stack for each capturing group as in a .NET / PyPi regex libraries, you need to use a 2 step approach: 1) match the strings as whole streaks of text, and then 2) post-process to get the values required.
var s = "2(3)(4)(5) A(B)(C)(D)";
var rx = /[^()\s]+(?:\([^)]*\))*/g;
var res = [], m;
while(m=rx.exec(s)) {
res.push(m[0].split(/[()]+/).filter(Boolean));
}
console.log(res);
I added \s to the negated character class [^()] since I added the examples as a single string.
Pattern details
[^()\s]+ - 1 or more chars other than (, ) and whitespace
(?:\([^)]*\))* - 0 or more sequences of:
\( - a (
[^)]* - 0+ chars other than )
\) - a )
The splitting regex is [()]+ that matches 1 or more ) or ( chars, and filter(Boolean) removes empty items.
You cannot have an undetermined number of capture groups. The number of capture groups you get is determined by the regular expression, not by the input it parses. A capture group that occurs within another repetition will indeed only retain the last of those repetitions.
If you know the maximum number of repetitions you can encounter, then just repeat the pattern that many times, and make each of them optional with a ?. For instance, this will capture up to 4 items within parentheses:
([^()]*)(?:\(([^)]*)\))?(?:\(([^)]*)\))?(?:\(([^)]*)\))?(?:\(([^)]*)\))?
It's not an error. It's just that in regex when you repeat a capture group (...)* that only the last occurence will be put in the backreference.
For example:
On a string "a,b,c,d", if you match /(,[a-z])+/ then the back reference of capture group 1 (\1) will give ",d".
If you want it to return more, then you could surround it in another capture group.
--> With /((?:,[a-z])+)/ then \1 will give ",b,c,d".
To get those numbers between the parentheses you could also just try to match the word characters.
For example:
var str = "2(3)(14)(B)";
var matches = str.match(/\w+/g);
console.log(matches);

javascript regex - extract number from string

Given "1/2009 stay longer" or "34/1874 got to go", how can I get the digit right after the "/" using regex.
'1/2009'.match(/\d+\/(\d)\d\d\d/g)[0] is returning 1/2009 which is not what I want. thx
Your RegEx works, if you want single digit right after /
Your regex \d+\/(\d)\d\d\d will match digits / then four digits and add first digit after slash in captured group.
Note that 0th captured group will contain complete matched string. g flag is not necessary as there is only one instance of numbers in that pattern.
You can use this regex, but use first index to get the digit right after slash.
'1/2009'.match(/\d+\/(\d)\d\d\d/g)[1]
^ : Get me the value from first captured group.
And this regex can be optimized to below
.match(/\/(\d)/)[1]
This will match the number followed by /. And use the first captured group to extract the number.
<input type="text" onblur="console.log(this.value.match(/\/(\d)/)[1])" />
To get all digits after /
Just add + quantifier to \d in the captured group.
.match(/\/(\d+)/)[1]
Try
var string = "1/2009 stay longer";
console.log(string.match(/\/(\d+)/)[1]);
\d+ matches one or more digits. If you're only interested in capturing the digit right after /, use string.match(/\/(\d)/ instead.
You can use exec method of regExp object also:
console.log(/\d+\/(\d).*/.exec('1/2009')[1]);

Categories

Resources