Как заставить эту странную строку взорваться в PHP?
У меня есть строка, подобная следующей
DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]
Приведенная выше строка является своего рода отформатированной в группах, которая выглядит следующим образом:
A-B[C]-D-E-[F]-G-[H]
Я думаю, что мне нравится обрабатывать некоторые из этих групп, и мне нравится делать что-то вроде взрыва.
Я говорю "нравится", потому что я попробовал этот код:
$string = 'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]';
$parts = explode( '-', $string );
print_r( $parts );
И я получаю следующий результат:
Array
(
[0] => DAS
[1] => 1111[DR
[2] => Helpfull
[3] => R]
[4] => RUN
[5] =>
[6] => [121668688374]
[7] => N
[8] => [+helpfull_+string]
)
Что это не то, что мне нужно.
Что мне нужно, так это следующий вывод:
Array
(
[0] => DAS
[1] => 1111[DR-Helpfull-R]
[2] => RUN
[3] =>
[4] => [121668688374]
[5] => N
[6] => [+helpfull_+string]
)
Может кто-нибудь, пожалуйста, предложите хороший и элегантный способ взорвать эту строку так, как мне это нужно?
Что я забыл упомянуть, так это то, что строка может содержать больше или меньше групп. Примеры:
DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]
DAS-1111[DR-Helpfull-R]-RUN--[121668688374]
DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]-anotherPart
Обновление 1
Как упоминал @axiac, preg_split
может выполнить эту работу. Но не могли бы вы, пожалуйста, помочь с регулярным выражением сейчас?
Я попробовал это, но, похоже, это неверно:
(?!\]\-)\-
3 answers
Код:
$str = 'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]';
$re = '/([^-[]*(?:\[[^\]]*\])?[^-]*)-?/';
$matches = array();
preg_match_all($re, $str, $matches);
print_r($matches[1]);
Его вывод:
Array
(
[0] => DAS
[1] => 1111[DR-Helpfull-R]
[2] => RUN
[3] =>
[4] => [121668688374]
[5] => N
[6] => [+helpfull_+string]
[7] =>
)
В позиции 7
на выходе есть дополнительное пустое значение. Это появляется из-за квантора повторений с нулем или одним (?
), размещенного в конце regex
. Квантификатор необходим, потому что без него последний фрагмент (с индексом 6
) не сопоставляется.
Вы можете удалить ?
после последнего -
и задать таким образом, чтобы тире (-
) всегда совпадало. В этом случае вы должны добавить дополнительный -
к своим входным данным строка.
Регулярное выражение
( # start of the 1st subpattern
# the captured value is returned in $matches[1]
[^-[]* # match any character but '-' and '[', zero or more times
(?: # start of a non-capturing subpattern
\[ # match an opening square bracket ('[')
[^\]]* # match any character but ']', zero or more times
\] # match a closing square bracket (']')
)? # end of the subpattern; it is optional (can appear 0 or 1 times)
[^-]* # match any character but '-', zero or more times
) # end of the 1st subpattern
-? # match an optional dash ('-')
Вместо того, чтобы взрываться, вы должны попытаться соответствовать следующему шаблону:
(?:^|-)([^-\[]*(?:\[[^\]]+\])?)
$regex = '/(?:^|-)([^-\[]*(?:\[[^\]]+\])?)/';
$tests = array(
'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]',
'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]',
'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]-anotherPart'
);
foreach ($tests as $test) {
preg_match_all($regex, $test, $result);
print_r($result[1]);
}
Вывод:
// DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]
Array
(
[0] => DAS
[1] => 1111[DR-Helpfull-R]
[2] => RUN
[3] =>
[4] => [121668688374]
[5] => N
[6] => [+helpfull_+string]
)
// DAS-1111[DR-Helpfull-R]-RUN--[121668688374]
Array
(
[0] => DAS
[1] => 1111[DR-Helpfull-R]
[2] => RUN
[3] =>
[4] => [121668688374]
)
// DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]-anotherPart
Array
(
[0] => DAS
[1] => 1111[DR-Helpfull-R]
[2] => RUN
[3] =>
[4] => [121668688374]
[5] => N
[6] => [+helpfull_+string]
[7] => anotherPart
)
Этот случай идеально подходит для метода (*SKIP)(*FAIL)
. Вы хотите разделить свою строку на дефисы, если они не заключены в квадратные скобки.
Легко. Просто дисквалифицируйте эти дефисы в качестве разделителей следующим образом:
Шаблон: ~\[[^]]+\](*SKIP)(*FAIL)|-~
( Демонстрация шаблона)
Код: ( Демонстрационный)
$strings=['DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]',
'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]',
'DAS-1111[DR-Helpfull-R]-RUN--[121668688374]-N-[+helpfull_+string]-anotherPart'];
foreach($strings as $string){
var_export(preg_split('~\[[^]]+\](*SKIP)(*FAIL)|-~',$string));
echo "\n\n";
}
Вывод:
array (
0 => 'DAS',
1 => '1111[DR-Helpfull-R]',
2 => 'RUN',
3 => '',
4 => '[121668688374]',
5 => 'N',
6 => '[+helpfull_+string]',
)
array (
0 => 'DAS',
1 => '1111[DR-Helpfull-R]',
2 => 'RUN',
3 => '',
4 => '[121668688374]',
)
array (
0 => 'DAS',
1 => '1111[DR-Helpfull-R]',
2 => 'RUN',
3 => '',
4 => '[121668688374]',
5 => 'N',
6 => '[+helpfull_+string]',
7 => 'anotherPart',
)