Моей первой идеей было preg_match_all('/\w+/', $string, $matches);
, но это дает результат, аналогичный тому, который вы получили. Проблема в том, что числа, разделенные точкой, очень неоднозначны. Это может означать как десятичную точку, так и конец предложения, поэтому нам нужен способ изменить строку таким образом, чтобы исключить двойное значение.
Например, в этом предложении у нас есть несколько частей, которые мы хотели бы сохранить как одно слово: "Look at this.My score is 3.14, and I am happy about it. It's not 334,3 and today's not 2009-12-12 11:12:13."
.
Мы начнем с создания словаря search-> replace для кодирования исключений во что-то, что не будет разделено:
$encode = array(
'/(\d+?)\.(\d+?)/' => '\\1DOT\\2',
'/(\d+?),(\d+?)/' => '\\1COMMA\\2',
'/(\d+?)-(\d+?)-(\d+?) (\d+?):(\d+?):(\d+?)/' => '\\1DASH\\2DASH\\3SPACE\\4COLON\\5COLON\\6'
);
Далее мы кодируем исключения:
foreach ($encode as $regex => $repl) {
$string = preg_replace($regex, $repl, $string);
}
Разделить строку:
preg_match_all('/\w+/', $string, $matches);
И преобразовать закодированное слово обратно:
$decode = array(
'search' => array('DOT', 'COMMA', 'DASH', 'SPACE', 'COLON'),
'replace' => array('.', ',', '-', ' ', ':' )
);
foreach ($matches as $k => $v) {
$matches[$k] = str_replace($decode['search'], $decode['replace'], $v);
}
$matches
теперь содержит оригинальное предложение, разбитое на слова с правильными исключениями.
Вы можете сделать регулярное выражение, используемое в исключениях, таким простым или сложным, как вам нравится, но некоторая двусмысленность всегда будет проходить, например, два отправления с первым, заканчивающимся, а следующий, начинающийся с числа: Number of the counting shall be 3.3 only and nothing but the 3.5 is right out..