I need a regex to match:
_Sample welcome text_
or Sample _welcome_ _text_
but not Sample_welcome_text
i.e there can be (space or nothing) before the opening underscore and (space or nothing) after the closing underscore.
I have tried using this:
/_(?:(?! ))(.*?)[^ ]_/gmi
Though it works but unfortunately it matches Sample_welcome_text
CodePudding user response:
You could use an alternation to either start with optional whitespace chars followed by an underscore, or the other way around.
Note that \s
can also match newlines. You could match mere spaces instead if that is required, or [^\S\n]*
to exclude newlines.
^\s*_.*|.*_\s*$
const regex = /^\s*_.*|.*_\s*$/;
[
"Sample welcome text_",
"Sample _welcome_ _text_",
"Sample_welcome_text"
].forEach(s =>
console.log(`${s} --> ${regex.test(s)}`)
)
CodePudding user response:
You could use lookbehind and lookahead assertion for searching text which surrounded by underscores, and there can be (space or nothing/start of string) before the opening underscore, (space or nothing/end of string) after the closing underscore.
/(?<=[ ] |^)_(.*?)_(?=[ ] |$)/gmi
Demo: https://regex101.com/r/t41Fkm/1
CodePudding user response:
You can use a positive lookbehind and lookahead for either whitespace or start/end of string, and reference the word in capture group 1: (.*?)
const regex = /(?<=\s|^)_(.*?)_(?=\s|$)/gs;
[
"Sample welcome text_",
"Sample _welcome_ _text_",
"Sample_welcome_text"
].forEach(str => {
let matches = [...str.matchAll(regex)].map(m => m[1]);
console.log(str, '=>', matches);
});
If you are concerned about Safari not supporting lookbehind, you can turn the lookbehind into capture group, and reference capture group 2 instead:
const regex = /(\s|^)_(.*?)_(?=\s|$)/gs;
[
"Sample welcome text_",
"Sample _welcome_ _text_",
"Sample_welcome_text"
].forEach(str => {
let matches = [...str.matchAll(regex)].map(m => m[2]);
console.log(str, '=>', matches);
});
Learn more about regex: https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex