Something like this might help:
const string = '&a.b.c. &a.b.c& .&a.b.c.&. *;a.b.c&*. a.b&.c& .&a.b.&&dc.& &ê.b..c&';
const result = string.split(' ').map(s => /^[^a-zA-Z0-9ê]*([\w\W]*?)[^a-zA-Z0-9ê]*$/g.exec(s)[1]).join(' ');
console.log(result);
Note that this is not one single regex, but uses JS help code.
Rough explanation: We first split the string into an array of strings, divided by spaces. We then transform each of the substrings by stripping
the leading and trailing special characters. We do this by capturing all special characters with [^a-zA-Z0-9ê]*
, because of the leading ^
character it matches all characters except those listed, so all special characters. Between these two groups we capture all relevant characters with ([\w\W]*?)
. \w
catches words, \W
catches non-words, so \w\W
catches all possible characters. By appending the ?
after the *
, we make the quantifier *
lazy, so that the group stops catching as soon as the next group, which catches trailing special characters, catches something. We also start the regex with a ^
symbol and end it with an $
symbol to capture the entire string (they respectively set anchors to the start end the end of the string). With .exec(s)[1]
we then execute the regex on the substring and return the first capturing group result in our transform function. Note that this might be null if a substring does not include proper characters. At the end we join the substrings with spaces.