I want separate the sentence
hey ! there you are
to
["hey!","there you are"]
in js. now I found that
(?<=\!)
keep separator with before element. but what if I want to use the rule to the "!!" or "!!!"? so my goal is change to separate sentence from
hey! there!!! you are!!!!
to
["hey!","there!!!", "you are!!!!"]
but is it possible?
I tried to \(?<=! )
or \(?<=\ !)
but fail.
I don't know even it possible to get !, !!..n by once
CodePudding user response:
Based on your needs my solution was to first get the exclamations, then get the strings (split by exclamations).
This method creates two arrays, one of exclamations and one of the strings.
Then I just loop over them, concatenate them, and push into a new array.
As a starting point it should be enough, you can always modify and built on top of this.
const str = 'hey! there!!! you are!!!!';
const exclamations = str.match(/! /g);
const characters = str.split(/! /).filter(s => s.trim());
let newArr = [];
for (i = 0; i < characters.length; i ) {
newArr.push(characters[i].trim() exclamations[i]);
}
console.log(newArr); // ["hey!","there!!!","you are!!!!"]
CodePudding user response:
You could use split with 2 lookarounds, asserting !
to the left and not !
to the right. If you want to remove the leading whitespace chars before the exclamation mark you could do some sanitizing:
const regex = /(?<=!)(?!!)/g;
[
"hey! there!!! you are!!!!",
"hey ! there you are"
].forEach(s =>
console.log(
s.split(regex)
.map(s => s.replace(/\s !/, "!").trim())
)
);
Another option could be to match the parts instead of splitting:
[^\s!].*?(?:!(?!!)|$)
See a regex demo.
const regex = /[^\s!].*?(?:!(?!!)|$)/g;
[
"hey! there!!! you are!!!!",
"hey ! there you are"
].forEach(s =>
console.log(s.match(regex))
);
CodePudding user response:
In addition to the elegant solution by The fourth bird, this specific requirement can be met by simply splitting on the regex, (?<=!)\s |$
which can be explained as "One or more whitespace characters, or end of line, preceded by a !
".
const regex = /(?<=!)\s |$/;
[
"hey! there!!! you are!!!!",
"hey ! there you are"
].forEach(s =>
console.log(
s.split(regex)
.map(s => s.replace(/\s !/, "!").trim())
)
);
CodePudding user response:
Here is yet another solution using a .split()
and .reduce()
. This does not use a lookbehind, for those concerned about Safari and other browsers not supporting it:
[
'hey ! there you are',
'hey! there!!! you are!!!!'
].forEach(str => {
let result = str
.split(/( *! *)/) // split and keep split pattern because of parenthesis
.filter(Boolean) // filter out empty items
.reduce((acc, val, idx) => {
if(idx % 2) {
// ! split pattern => combine with previous array item
acc[acc.length - 1] = val.trim();
} else {
acc.push(val);
}
return acc;
}, []);
console.log(str, ' => ', result);
});
Output:
hey ! there you are => [
"hey!",
"there you are"
]
hey! there!!! you are!!!! => [
"hey!",
"there!!!",
"you are!!!!"
]