php: разделить строку на 3 части двумя разделителями, где первый и последний разделители - буквы или цифры соответственно

Любые идеи, как разбить строку на 3 части, где двумя «разделителями», где первый и последний «разделители» являются буквами или цифрами соответственно?

$str = "%@-H-e-l-l-o-7-9#$%";

будет разбито так:

$arr=("%@-","H-e-l-l-o-7-9", "#$%");

и

$str = "Hi$73";

будет разбито так:

$arr=("","Hi$73", "");

и

$str = "Беларусь!";

будет разбито так:

$arr=("","Беларусь", "!");

и

$str = "!";

будет разбито так:

$arr=("!","", "");

и

$str = "";

будет разбито так:

$arr=("","", "");

и

$str = "ў55ЎW";

будет разбито так:

$arr=("","ў55ЎW", "");

что означает, что он возвращает массив, состоящий из 3-х элементов (всегда), причем первый и последний символы второго элемента являются цифрами или буквами латиницы/кириллицы, а первый и последний(третий) элементы этого массива содержат абсолютно без цифр и букв, и соединение этих строк является исходной строкой

Спасибо.


person Haradzieniec    schedule 28.01.2017    source источник


Ответы (2)


Вот как это сделать:

$in = array(
"%@-H-e-l-l-o-7-9#$%",
"Hi$73",
"Беларусь!",
"!",
"",
"ў55ЎW",
'$abc$$$',
"асоба_",
"34.5",
'#_!',
);

foreach($in as $elem) {
    preg_match('/^([^\pL\pN]*)((?=[\pL\pN]|$)[^_]*(?<=[\pL\pN])|^)?([^\pL\pN]*)$/u', $elem, $m);
    printf("'%15s'%s'%10s'\t%s'%10s'\t%s'%10s'%s", "$elem","=> (1): ",$m[1],"(2): ",$m[2], "(3): ",$m[3],"\n");

}

Где:

  • \pL обозначает любую букву на любом языке
  • \pN обозначает любое число на любом языке

Вывод:

'%@-H-e-l-l-o-7-9#$%'=> (1): '       %@-'   (2): 'H-e-l-l-o-7-9'    (3): '       #$%'
'          Hi$73'=> (1): '          '   (2): '     Hi$73'   (3): '          '
'Беларусь!'=> (1): '          ' (2): 'Беларусь' (3): '         !'
'              !'=> (1): '         !'   (2): '          '   (3): '          '
'               '=> (1): '          '   (2): '          '   (3): '          '
'        ў55ЎW'=> (1): '          ' (2): '   ў55ЎW' (3): '          '
'        $abc$$$'=> (1): '         $'   (2): '       abc'   (3): '       $$$'
'    асоба_'=> (1): '          '    (2): 'асоба'    (3): '         _'
'           34.5'=> (1): '          '   (2): '      34.5'   (3): '          '
'            #_!'=> (1): '       #_!'   (2): '          '   (3): '          '
person Toto    schedule 28.01.2017
comment
у вас есть Array([0] => Hi$73 [1] => [2] => Hi [3] => $73) . Но ОП хотел $arr=("","Hi$73", ""); - person RomanPerekhrest; 28.01.2017
comment
@RomanPerekhrest: Правда, я отредактировал код, вставил $ в класс символов. - person Toto; 28.01.2017
comment
Извините, что принял как лучший ответ, а не ваш. Оба ответа идеальны, но благодаря @RomanPerekhrest он нашел небольшую ошибку в вашем ответе. Это единственная причина, по которой я знаю, как отметить принятый ответ. В остальном оба идеальны. И большое спасибо вам обоим. - person Haradzieniec; 28.01.2017
comment
@Haradzieniec: Не волнуйся, со мной все в порядке. До меня ответил Роман Перехрест. - person Toto; 28.01.2017
comment
@Toto, и похоже, что ваш код не работает для $abc$$$: ‹?php $in = array( $abc$$$ ); foreach($in as $elem) { preg_match('/^(\PL*)([\pL\d$-]*)(\PL*)$/u', $elem, $m); print_r ($ м); } ?› возвращает E_NOTICE : тип 8 -- Неопределенная переменная: abc (я не изменил ваш код, чтобы показать ошибку, хотя массив состоит из одного элемента). - person Haradzieniec; 28.01.2017
comment
@Haradzieniec: Смотрите мое редактирование, теперь все в порядке? Я использую границу слова, чтобы различить не словесную часть/словную (и более) часть - person Toto; 28.01.2017
comment
@Тото, большое спасибо. Похоже, что подчеркивание _ - это проблема с новым кодом (перепробовал много тестов после этого вашего комментария). _ рассматривается как буква :( preg_match('/^(\PL*)(\b.*\b)?(\PL*)$/u', асоба_, $arr); $arr[3] вместо этого of _ и к сожалению $arr[2]=асоба_ соответственно. - person Haradzieniec; 28.01.2017
comment
И еще одно: preg_match('/^(\PL*)(\b.*\b)?(\PL*)$/u', '34.5', $m); print_r ($ м); создает массив ( [0] => 34,5 [1] => 34,5 [2] => [3] => ), но 34,5 должно быть в [2]-м, а не в первом. Тем не менее, спасибо за вашу помощь. Сегодня я многое сделал благодаря тебе. - person Haradzieniec; 29.01.2017
comment
@Haradzieniec:Посмотрите мое новое редактирование, теперь оно работает для любых тестовых случаев, 34.5, асоба_ и #_!, эти 2 последних не работают с регулярным выражением RomanPerekhrest. - person Toto; 29.01.2017
comment
Я подтверждаю #_! и асоба_ не работает должным образом для кода, предложенного @RomanPerekhrest. Большое спасибо. Таким образом, я должен принять ваш ответ как лучший? Роман, извините за это. - person Haradzieniec; 01.02.2017

Решение с использованием функций preg_match и array_slice:

$str = "%@-H-e-l-l-o-7-9#$%";

preg_match('/^([^\w]*)(\w+.*\w+|\w)?([^\w]*)$/iu', $str, $matches);
$parts = array_slice($matches, 1);

print_r($parts);

Выход:

Array
(
    [0] => %@-
    [1] => H-e-l-l-o-7-9
    [2] => #$%
)

Этот подход будет работать для всех ваших представленных вариантов ввода.

person RomanPerekhrest    schedule 28.01.2017
comment
похоже, ваш код не работает для 1 буквы. Пустой массив для ‹?php $str = к; preg_match('/^([^\w]*)(\w+.*\w+)?([^\w]*)$/iu', $str, $matches); $parts = array_slice($matches, 1); print_r ($ частей); ?› - person Haradzieniec; 28.01.2017
comment
@Haradzieniec, проверь мое обновление. Теперь он должен работать нормально - person RomanPerekhrest; 29.01.2017
comment
Похоже, это работает! Единственная проблема, которую я нашел, _ подчеркивание рассматривается как буква, но это из-за \w, который является любым символом слова (буква, цифра, подчеркивание). К подчеркиванию вопросов нет. Это может быть отдельный вопрос SO. Большое спасибо за твою помощь! Я очень ценю это. Спасибо! - person Haradzieniec; 29.01.2017