复杂的正则表达式与preg_replace,替换不在[和]内的单词

I'm having trouble finding a correct regex to achieve what I want.

I have a sentence like that :

Hi, my name is Stan, you are welcome, hello.

and I would like to transform it like that :

[hi|hello|welcome], my name is [stan|jack] you are [hi|hello|welcome] [hi|hello|welcome].

Right now my regex is half working, because somes words are not replaced, and those replaced are deleting some characters

Here is my test code

<?php 

$test = 'Hi, my name is Stan, you are welcome, hello.';

$words = array(
    array('hi', 'hello', 'welcome'),
    array('stan', 'jack'),
);

$result = $test;
foreach ($words as $group) {
    if (count($group) > 0) {
        $replacement = '[' . implode('|', $group) . ']';
        foreach ($group as $word) {
            $result = preg_replace('#([^\[])' . $word . '([^\]])#i', $replacement, $result);
        }
    }
}

echo $test . '<br />' . $result;

Any help will be appreciated

The regex you are using is overcomplicated. You simply need to use a regex substitution using regular brackets ():

<?php 

$test = 'Hi, my name is Stan, you are welcome, hello.';

$words = array(
        array('hi', 'hello', 'welcome'),
        array('stan', 'jack'),
        );

$result = $test;
foreach ($words as $group) {
    if (count($group) > 0) {
        $imploded = implode('|', $group);
        $replacement = "[$imploded]";
        $search = "($imploded)";
        $result = preg_replace("/$search/i", $replacement, $result);
    }
}

echo $test . '<br />' . $result;

preg_replace supports array as parameter. No need to iterate with a loop.

$s = array("/(hi|hello|welcome)/i", "/(stan|jack)/i");
$r = array("[hi|hello|welcome]", "[stan|jack]");
preg_replace($s, $r, $str); 

or dynamically

$test = 'Hi, my name is Stan, you are welcome, hello.';
$s = array("hi|hello|welcome", "stan|jack");
$r = array_map(create_function('$a','return "[$a]";'), $s);
$s = array_map(create_function('$a','return "/($a)/i";'), $s);
echo preg_replace($s, $r, $str);
//[hi|hello|welcome], my name is [stan|jack], you are [hi|hello|welcome], [hi|hello|welcome].

Your regular expression:

'#([^\[])' . $word . '([^\]])#i'

matches one character before and after $word as well. And as they do, they replace it. So your replacement string needs to reference these parts, too:

'$1' . $replacement . '$2'

Demo