If got you right, the offending case is the second match in your sample that has a . at the and of the match. With a PCRE regex with could solve this easily with lookbehind assertion (?<!\.)
like that:
((\w*?)((:\/\/)|www|\w\.{1}\w{2,})[^"<\s]+(?<!\.))(?![^<>]*>|[^"]*?<\/a)
Unfortunately, this does not work in (current) JavaScript's regex engines. As an alternative we can use the (?:(?!avoid).)+
pattern to exclude add the dot before your inner everything-but pattern [^"<\s]+
; however, it get's a bit messy since you have to use multiple alternations sorted by length (long to short) to account for the case where there is a final .
before <|"|\s
:
((\w*?)((:\/\/)|www|\w\.{1}\w{2,})(:?(?!\.\s|\s|\."|"\.<|<).)+)(?![^<>]*>|[^"]*?<\/a)
const regex = /((\w*?)((:\/\/)|www|\w\.{1}\w{2,})(:?(?!\.\s|\s|\."|"\.<|<).)+)(?![^<>]*>|[^"]*?<\/a)/g;
const str = `djfhjkshd fjkshkdjfhsjkdhfjk jdsfh ksjdfksd fkdsf dkfh kjh<br>You can open your link here: https://testask.com/item/45e20490-2b86-4b6a-8772-5ed96f64de52. dsjfklj skldjfklsdjfkl. dsjfjshdfjk skdhfshdfj skdhfjshfjsahfjhasjfh shfk.<br>sdkfhklsdjf kljsdklf kdsljfkljafkljkl .`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
console.log(m[0]);
// The result can be accessed through the `m`-variable.
//m.forEach(match => {
// console.log(`Found match: ${match}`);
//});
}
The easiest solution is, however, simply trim the trailing dot afterwards.