Replace a multiple times a substring in javascript - javascript

I need to replace everything between : and , with a | multiple times.
I have a server list like server1:127.0.0.1,server2:127.0.0.2,server3:127.0.0.3.
Basically, I need to remove all the IPs and replace them with some |.
So far I was able to do this:
resultList = serverList.replace(/:.*,/g, '|')
The problem is that the result list is server1|server3:127.0.0.3.
How can I replace every occurrence?

/:.*,/ is greedily matching :127.0.0.1,server2:127.0.0.2. Remember that quantifiers like * will match as much as they can while still allowing the rest of the pattern to match.
Consider specifying [^,] instead of .. This will exclude commas from matching and therefore limit the match to just the region you want to remove.
resultList = serverList.replace(/:[^,]*,/g, '|')

You could take a lazy approach with ? (Matches as few characters as possible).
var string = 'server1:127.0.0.1,server2:127.0.0.2,server3:127.0.0.3';
console.log(string.replace(/:.*?(,|$)/g, '|'));

Related

javascript regex insert new element into expression

I am passing a URL to a block of code in which I need to insert a new element into the regex. Pretty sure the regex is valid and the code seems right but no matter what I can't seem to execute the match for regex!
//** Incoming url's
//** url e.g. api/223344
//** api/11aa/page/2017
//** Need to match to the following
//** dir/api/12ab/page/1999
//** Hence the need to add dir at the front
var url = req.url;
//** pass in: /^\/api\/([a-zA-Z0-9-_~ %]+)(?:\/page\/([a-zA-Z0-9-_~ %]+))?$/
var re = myregex.toString();
//** Insert dir into regex: /^dir\/api\/([a-zA-Z0-9-_~ %]+)(?:\/page\/([a-zA-Z0-9-_~ %]+))?$/
var regVar = re.substr(0, 2) + 'dir' + re.substr(2);
var matchedData = url.match(regVar);
matchedData === null ? console.log('NO') : console.log('Yay');
I hope I am just missing the obvious but can anyone see why I can't match and always returns NO?
Thanks
Let's break down your regex
^\/api\/ this matches the beginning of a string, and it looks to match exactly the string "/api"
([a-zA-Z0-9-_~ %]+) this is a capturing group: this one specifically will capture anything inside those brackets, with the + indicating to capture 1 or more, so for example, this section will match abAB25-_ %
(?:\/page\/([a-zA-Z0-9-_~ %]+)) this groups multiple tokens together as well, but does not create a capturing group like above (the ?: makes it non-captuing). You are first matching a string exactly like "/page/" followed by a group exactly like mentioned in the paragraph above (that matches a-z, A-Z, 0-9, etc.
?$ is at the end, and the ? means capture 0 or more of the precending group, and the $ matches the end of the string
This regex will match this string, for example: /api/abAB25-_ %/page/abAB25-_ %
You may be able to take advantage of capturing groups, however, and use something like this instead to get similar results: ^\/api\/([a-zA-Z0-9-_~ %]+)\/page\/\1?$. Here, we are using \1 to reference that first capturing group and match exactly the same tokens it is matching. EDIT: actually, this probably won't work, since the text after /api/ and the text after /page/ will most likely be different, carrying on...
Afterwards, you are are adding "dir" to the beginning of your search, so you can now match someting like this: dir/api/abAB25-_ %/page/abAB25-_ %
You have also now converted the regex to a string, so like Crayon Violent pointed out in their comment, this will break your expected funtionality. You can fix this by using .source on your regex: var matchedData = url.match(regVar.source); https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
Now you can properly match a string like this: dir/api/11aa/page/2017 see this example: https://repl.it/Mj8h
As mentioned by Crayon Violent in the comments, it seems you're passing a String rather than a regular expression in the .match() function. maybe try the following:
url.match(new RegExp(regVar, "i"));
to convert the string to a regular expression. The "i" is for ignore case; don't know that's what you want. Learn more here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp

Regexp to capture comma separated values

I have a string that can be a comma separated list of \w, such as:
abc123
abc123,def456,ghi789
I am trying to find a JavaScript regexp that will return ['abc123'] (first case) or ['abc123', 'def456', 'ghi789'] (without the comma).
I tried:
^(\w+,?)+$ -- Nope, as only the last repeating pattern will be matched, 789
^(?:(\w+),?)+$ -- Same story. I am using non-capturing bracket. However, the capturing just doesn't seem to happen for the repeated word
Is what I am trying to do even possible with regexp? I tried pretty much every combination of grouping, using capturing and non-capturing brackets, and still not managed to get this happening...
If you want to discard the whole input when there is something wrong, the simplest way is to validate, then split:
if (/^\w+(,\w+)*$/.test(input)) {
var values = input.split(',');
// Process the values here
}
If you want to allow empty value, change \w+ to \w*.
Trying to match and validate at the same time with single regex requires emulation of \G feature, which assert the position of the last match. Why is \G required? Since it prevents the engine from retrying the match at the next position and bypass your validation. Remember than ECMA Script regex doesn't have look-behind, so you can't differentiate between the position of an invalid character and the character(s) after it:
something,=bad,orisit,cor&rupt
^^ ^^
When you can't differentiate between the 2 positions, you can't rely on the engine to do a match-all operation alone. While it is possible to use a while loop with RegExp.exec and assert the position of last match yourself, why would you do so when there is a cleaner option?
If you want to savage whatever available, torazaburo's answer is a viable option.
Live demo
Try this regex :
'/([^,]+)/'
Alternatively, strings in javascript have a split method that can split a string based on a delimeter:
s.split(',')
Split on the comma first, then filter out results that do not match:
str.split(',').filter(function(s) { return /^\w+$/.test(s); })
This regex pattern separates numerical value in new line which contains special character such as .,,,# and so on.
var val = [1234,1213.1212, 1.3, 1.4]
var re = /[0-9]*[0-9]/gi;
var str = "abc123,def456, asda12, 1a2ass, yy8,ghi789";
var re = /[a-z]{3}\d{3}/g;
var list = str.match(re);
document.write("<BR> list.length: " + list.length);
for(var i=0; i < list.length; i++) {
document.write("<BR>list(" + i + "): " + list[i]);
}
This will get only "abc123" code style in the list and nothing else.
May be you can use split function
var st = "abc123,def456,ghi789";
var res = st.split(',');

Get string between tags when multiple tags present

Just trying to figure this one out as regex is nowhere near my strong point :(
Basically I'm trying to get the value between bbcode tags: That could look like either of the following:
[center]text[/center]
[left][center]text[/center][/left]
[right][left][center]text[/center][/left][/right]
And currently have this hideous if else block of code to prevent it getting large like the third option above.
if (/\[left\]|\[\/left\]/.test(text[2])) {
// set the value in the [left][/left] tags
text[2] = text[2].match(/\[left\](.*?)\[\/left\]/)[1];
} else if (/\[right\]|\[\/right\]/.test(text[2])) {
// set value in the [right][/right] tags
text[2] = text[2].match(/\[right\](.*?)\[\/right\]/)[1];
} else if (/\[center\]|\[\/center\]/.test(text[2])) {
// set value in the [right][/right] tags
text[2] = text[2].match(/\[center\](.*?)\[\/center\]/)[1];
}
What I'd like to do is shorten it down to a single regex expression to grab that value text from the above examples, I've gotten down to an expression like this:
/\[(?:center|left|right)\](.*?)\[\/(?:center|left|right)\]/
But as you can see in this RegExr demo, it doesn't match what I need it to.
How can I achieve this?
Note
It should only match left|right|center as the selected text could also have various other bbcode tags.
If the string looks like this:
[center][left][img]/link/to/img.png[/img][/left][/center]
I want to get what is between the left|center|right tags which in this case would be:
[img]/link/to/img.png[/img]
More examples:
[center][url=lintosomething.com]LINK TEXT[/url][/center]
Should only get: [url=lintosomething.com]LINK TEXT[/url]
Or
[center]egibibskdfbgfdkfbg sd fgkgb fkgbgk fhwo3g regbiurb geir so go to [url=lintosomething.com]LINK TEXT[/url] and ibgri gbenkenbieurgnerougnerogrnreog erngo[/center]
Wanting:
egibibskdfbgfdkfbg sd fgkgb fkgbgk fhwo3g regbiurb geir so go to [url=lintosomething.com]LINK TEXT[/url] and ibgri gbenkenbieurgnerougnerogrnreog erngo
Edit: Ok, I think this fits your needs.
My regex:
/[^\]\[]*\[(\w+)[=\.\"\w]*\][^\]]+\[\/\1\][^\]\[]*/g
Explanation:
Match 0 or more characters that arent [ or ]
Match a single [
Match 1 or more of alpha characters, we'll use this later as a backreference
Match 0 or more of = . " or alpha characters
Match a single ]
Match 1 or more non [ characters
Match a single [
Match a single /
Match the same characters as step 3. (Our back reference)
Match a single ]
Match 0 or more characters that arent [ or ]
See it in action
However I would like to state that if you're going to be parsing bbcodes you're almost certainly better off just using a bbparser.
Why not just replace all those tags with empty string
var rawString; // your input string
var cleanedString = rawString.replace(~\[/?(left|right|center)\]~, '');
You could use a capturing group like this:
(?:\[\w+\])*(\w+)(?:\[\/\w+\])*
Or with a capture group named "value" like this:
(?:\[\w+\])*(?<value>\w+)(?:\[\/\w+\])*
The first and last groups are non-capturing... (?: ...)
And the middle group is capturing (\w+)
And the middle group if named like this (?<value>\w+)
Note: For simplicity, I replaced your center|left|right values with \w+ but you could swap them back in with no impact.
I use an app called RegExRX. Here's a screenshot with the RegEx and captured values.
Lots of ways you could tweak it. Good luck!

Regex to capture everything but consecutive newlines

What is the best way to capture everything except when faced with two or more new lines?
ex:
name1
address1
zipcode
name2
address2
zipcode
name3
address3
zipcode
One regex I considered was /[^\n\n]*\s*/g. But this stops when it is faced with a single \n character.
Another way I considered was /((?:.*(?=\n\n)))\s*/g. But this seems to only capture the last line ignoring the previous lines.
What is the best way to handle similar situation?
UPDATE
You can consider replacing the variable length separator with some known fixed length string not appearing in your processed text and then split. For instance:
> var s = "Hi\n\n\nBye\nCiao";
> var x = s.replace(/\n{2,}/, "#");
> x.split("#");
["Hi", "Bye
Ciao"]
I think it is an elegant solution. You could also use the following somewhat contrived regex
> s.match(/((?!\n{2,})[\s\S])+/g);
["Hi", "
Bye
Ciao"]
and then process the resulting array by applying the trim() string method to its members in order to get rid of any \n at the beginning/end of every string in the array.
((.+)\n?)*(you probably want to make the groups non-capturing, left it as is for readability)
The inner part (.+)\n? means "non-empty line" (at least one non-newline character as . does not match newlines unless the appropriate flag is set, followed by an optional newline)
Then, that is repeated an arbitrary number of times (matching an entire block of non-blank lines).
However, depending on what you are doing, regexp probably is not the answer you are looking for. Are you sure just splitting the string by \n\n won't do what you want?
Do you have to use regex? The solution is simple without it.
var data = 'name1...';
var matches = data.split('\n\n');
To access an individual sub section split it by \n again.
//the first section's name
var name = matches[0].split('\n')[0];

Javascript: How can I search and replace multiple items with matched groups?

Say I have a string like
"item:(one|two|three), item2:(x|y)"
Is there a single regex that could "factor" it into
"item:one, item:two, item:three, item2:x, item2:y"
Or must I resort to splitting and looping?
If I must split it up then how do I even turn
"item:(one|two|three)"
into
"item:one, item:two, item:three"
if the amount of things between the parentheses is variable? Are regexes useless for such a problem?
You could do it with a callback function:
str = str.replace(/(\w+):\(([^)]*)\)/gi, function(match,item,values)
{return item + ':' + values.split("|").join(', '+item+':')}
);
For every item, the first parentheses in the regex capture the item's name (i.e item) and the second set of (unescaped) parentheses capture the string of all values (i.e one|two|three). The latter are then split at | and joined together with , itemname: and then there is another item name appended to the beginning of the result.
This is probably the easiest way to combine regexes to find your data and split and join to build your new regex. The problem why it is not easier is, that you cannot capture an arbitrary number of consecutive values (one|two|three) in different capturing groups. You would only get the last one, if you tried to capture them individually.

Categories

Resources