Is it possible to make 2 replace operations in 1 Regex expression? - javascript

I have text data like below
aaa
bbb
ccc
And I should return 'aaa','bbb','ccc'
Currently I achieve this in 2 steps:
Replace [\r\n]+ with ','
Replace ($|^) with '
Is it possible to do the same via only 1 step?

Ok, if this is just for curiosity, you can do this with a function replacement value. I would never suggest actually using it for this purpose, but this should do it:
const s = `aaa
bbb
ccc`
const s2 = s.replace(/$|^|\n/g, (s) => s === '\n' ? "','" : "'")
console.log(s2)
But of course, in some sense, I'm cheating, not really using the RegEx fundamentals here, only putting the logic in a callback function.
So, yes, this can be done.
But please don't use this anywhere.
(Oh, and I simplified to only checking for '\n'. Obviously you could extend it to your [\r\n]+ as you like.)

You may use a more robust solution with the same approach as Scott suggested in his answer, but my suggestion is based on capturing groups that will be used to decide which replacement logic to use rather than listing all possible chars you need to replace.
So, here is the slightly modified solution:
const s = `aaa
bbb
ccc`
const s2 = s.replace(/$|^|([\r\n]+)/g, ($0,$1) => $1 ? "','" : "'")
console.log(s2)
POIs:
/$|^|([\r\n]+)/g pattern matches multiple occurrences of start or end of string or matches and captures 1+ occurrences of CRs or LFs into Group 1
Now, with ($0,$1), we have access to the whole match and Group 1 ($1)
If Group 1 is not undefined, if it matched, we replace with ',', else, we replace with ' ($1 ? "','" : "'").

No. At a time only one replacement keyword can be used.

Related

regex to remove certain characters at the beginning and end of a string

Let's say I have a string like this:
...hello world.bye
But I want to remove the first three dots and replace .bye with !
So the output should be
hello world!
it should only match if both conditions apply (... at the beginning and .bye at the end)
And I'm trying to use js replace method. Could you please help? Thanks
First match the dots, capture and lazy-repeat any character until you get to .bye, and match the .bye. Then, you can replace with the first captured group, plus an exclamation mark:
const str = '...hello world.bye';
console.log(str.replace(/\.\.\.(.*)\.bye/, '$1!'));
The lazy-repeat is there to ensure you don't match too much, for example:
const str = `...hello world.bye
...Hello again! Goodbye.`;
console.log(str.replace(/\.\.\.(.*)\.bye/g, '$1!'));
You don't actually need a regex to do this. Although it's a bit inelegant, the following should work fine (obviously the function can be called whatever makes sense in the context of your application):
function manipulate(string) {
if (string.slice(0, 3) == "..." && string.slice(-4) == ".bye") {
return string.slice(4, -4) + "!";
}
return string;
}
(Apologies if I made any stupid errors with indexing there, but the basic idea should be obvious.)
This, to me at least, has the advantage of being easier to reason about than a regex. Of course if you need to deal with more complicated cases you may reach the point where a regex is best - but I personally wouldn't bother for a simple use-case like the one mentioned in the OP.
Your regex would be
const rx = /\.\.\.([\s\S]*?)\.bye/g
const out = '\n\nfoobar...hello world.bye\nfoobar...ok.bye\n...line\nbreak.bye\n'.replace(rx, `$1!`)
console.log(out)
In English, find three dots, anything eager in group, and ending with .bye.
The replacement uses the first match $1 and concats ! using a string template.
An arguably simpler solution:
const str = '...hello world.bye'
const newStr = /...(.+)\.bye/.exec(str)
const formatted = newStr ? newStr[1] + '!' : str
console.log(formatted)
If the string doesn't match the regex it will just return the string.

How not to match a certain regexp in javascript?

I want to check if a variable do not match this regexp:
DEMO
So this is the pattern that match the regexp in my code:
rxAfterPrint = new RegExp(/^ *\+ *("(?:[^"]*)"|(?:[a-zA-Z]\w*)) *(.*)$/);
and in this way I check for matching:
var t2 = t[2].match(rxAfterPrint);
and now I want to create e varible t3 that dont match this pattern
How can I do this? can you please help me?
(Admitting I have an unfair advantage because I knew why this problem did arise: How can I interpret strings in textarea with JavaScript/jQuery?)
So my guess is you want to implement String concatenation as part of a print statement as follows:
<string> ::= '"' <character>* '"' | <variable>
<print> ::= 'print' <string> ('+' <string>)*
<print> ::= 'print' (<string> '+')* <string>
The two <print> actually express the same, using the 2nd version you can first (after matching /^ *print */) try to apply the pattern rxConcat as many times a possible and if this doesn't match, then you apply the 2nd expression rxStringValEOL to match the remainder (if no success, it's an invalid statement):
rxConcat = new RegExp(/ *(?:"([^"]*)"|([a-zA-Z]\w*)) *\+ */);
rxStringValEOL = new RegExp(/ *(?:"([^"]*)"|([a-zA-Z]\w*)) *$/);
This also shows that it is pretty difficult to design a language that is easy for the programmers and for those who write the compilers.
It's really unclear what you mean by "I want to create a variable that don't match this pattern". Since t2 is your match, it seems like you want t3 to be objects that don't match.
Because you're anchoring to the start of the string (^), this is a really great place to use a negative lookahead with almost the identical regex. Literally, all I did was surround it with (?! and ) and .* at the end..
output1.value = input.value.match(/^(?! *\+ *("(?:[^"]*)"|(?:[a-zA-Z]\w*)) *(.*)).*$/gm).join("\r\n")
An alternative is to use replace() like so, but I would believe match() is the better option.
output2.value = input.value.replace(/(^ *\+ *("(?:[^"]*)"|(?:[a-zA-Z]\w*)) *(.*)$\s*)+/gm,"")
For both cases, I added the global and multiline to easily test several lines at once. If you're only testing one, remove both the g and the m, otherwise it could cause bugs by incorrectly telling you a string passed or failed when it didn't.
Demo: JSFiddle

Extract specific chars from a string using a regex

I need to split an email address and take out the first character and the first character after the '#'
I can do this as follows:
'bar#foo'.split('#').map(function(a){ return a.charAt(0); }).join('')
--> bf
Now I was wondering if it can be done using a regex match, something like this
'bar#foo'.match(/^(\w).*?#(\w)/).join('')
--> bar#fbf
Not really what I want, but I'm sure I miss something here! Any suggestions ?
Why use a regex for this? just use indexOf to get the char at any given position:
var addr = 'foo#bar';
console.log(addr[0], addr[addr.indexOf('#')+1])
To ensure your code works on all browsers, you might want to use charAt instead of []:
console.log(addr.charAt(0), addr.charAt(addr.indexOf('#')+1));
Either way, It'll work just fine, and This is undeniably the fastest approach
If you are going to persist, and choose a regex, then you should realize that the match method returns an array containing 3 strings, in your case:
/^(\w).*?#(\w)/
["the whole match",//start of string + first char + .*?# + first string after #
"groupw 1 \w",//first char
"group 2 \w"//first char after #
]
So addr.match(/^(\w).*?#(\w)/).slice(1).join('') is probably what you want.
If I understand correctly, you are quite close. Just don't join everything returned by match because the first element is the entire matched string.
'bar#foo'.match(/^(\w).*?#(\w)/).splice(1).join('')
--> bf
Using regex:
matched="",
'abc#xyz'.replace(/(?:^|#)(\w)/g, function($0, $1) { matched += $1; return $0; });
console.log(matched);
// ax
The regex match function returns an array of all matches, where the first one is the 'full text' of the match, followed by every sub-group. In your case, it returns this:
bar#f
b
f
To get rid of the first item (the full match), use slice:
'bar#foo'.match(/^(\w).*?#(\w)/).slice(1).join('\r')
Use String.prototype.replace with regular expression:
'bar#foo'.replace(/^(\w).*#(\w).*$/, '$1$2'); // "bf"
Or using RegEx
^([a-zA-Z0-9])[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+#([a-zA-Z0-9-])[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$
Fiddle

Remove everything after the first instance of one of several characters

Say I have a string like:
var str = "Good morningX Would you care for some tea?"
Where the X could be one of several characters, like a ., ?, or !.
How can I remove everything after that character?
If it could only be one type of character, I would use indexOf and substr, but it looks like I need a different method to find the position in this case. Perhaps a regular expression?
Clarification: I do not know what character X is. I'd like to cut the string off at the first occurrence of any one of the specified characters.
Ok, further clarification:
What I'm actually doing is scrubbing posts from a website. I'm taking the first bit from each post and stitching them together. By 'bit', I mean characters before the first piece of punctuation. I need to cut everything off after that punctuation. Does that make sense?
Just replace everything within the [ and ] with your delimiters. Escape if necessary.
var str = "Good morning! Would you care for some tea?";
var beginning = str.split(/[.?!]/)[0];
// "Good morning"
Try this, If the X have this ',' character , then try below
var s = 'Good morning, would you care for some tea?';
s = s.substring(0, s.indexOf(','));
document.write(s);
Demo : http://jsfiddle.net/L4hna/490/
and if the X have '!' , then try below
var s = 'Good morning! would you care for some tea?';
s = s.substring(0, s.indexOf('!'));
document.write(s);
Demo : http://jsfiddle.net/L4hna/491/
Try this way for your requirement string.
Both are will return Good Morning
The below code will do as you expect:
var s = "Good morningX Would you care for some tea?";
s = s.substring(X, n != -1 ? n : s.length);
document.write(s);
http://jsfiddle.net/JEFnY/
The regex would be
str.replace(/(.*?)([\.\?\!])(.*)/i, '$1$2');
The first capturing group is a lazy expression to match everything before the next capturing group.
The second capturing group only looks for the characters that you specify - which in this case are .!?, all escaped.
The last capturing group is discarded. Hence the substitution string is $1$2, or the first two capturing groups together.

java script Regular Expressions patterns problem

My problem start with like-
var str='0|31|2|03|.....|4|2007'
str=str.replace(/[^|]\d*[^|]/,'5');
so the output becomes like:"0|5|2|03|....|4|2007" so it replaces 31->5
But this doesn't work for replacing other segments when i change code like this:
str=str.replace(/[^|]{2}\d*[^|]/,'6');
doesn't change 2->6.
What actually i am missing here.Any help?
I think a regular expression is a bad solution for that problem. I'd rather do something like this:
var str = '0|31|2|03|4|2007';
var segments = str.split("|");
segments[1] = "35";
segments[2] = "123";
Can't think of a good way to solve this with a regexp.
Here is a specific regex solution which replaces the number following the first | pipe symbol with the number 5:
var re = /^((?:\d+\|){1})\d+/;
return text.replace(re, '$15');
If you want to replace the digits following the third |, simply change the {1} portion of the regex to {3}
Here is a generalized function that will replace any given number slot (zero-based index), with a specified new number:
function replaceNthNumber(text, n, newnum) {
var re = new RegExp("^((?:\\d+\\|){"+ n +'})\\d+');
return text.replace(re, '$1'+ newnum);
}
Firstly, you don't have to escape | in the character set, because it doesn't have any special meaning in character sets.
Secondly, you don't put quantifiers in character sets.
And finally, to create a global matching expression, you have to use the g flag.
[^\|] means anything but a '|', so in your case it only matches a digit. So it will only match anything with 2 or more digits.
Second you should put the {2} outside of the []-brackets
I'm not sure what you want to achieve here.

Categories

Resources