Захватить необязательную группу в другой записи

Учитывая вход как

${first_name}, ${last_name}, ${create_date:(Y-m-d)}, ${submit_date:(Y-m-d)}

я могу использовать \${(.*)} чтобы захватить все в скобках. Когда суффикс появляется как на датах в примере, я хочу зафиксировать его как свою собственную группу. Как я могу сделать это с одним регулярным выражением?

0

Решение

Вы можете попробовать это,

\$\{([^:, ]*(?::\(([^)]*)\))?)\}

демонстрация,,, в котором общее значение (строка) внутри фигурной скобки фиксируется в group 1и необязательное значение (строка) фиксируется в group 2,

и вы можете попробовать это тоже, если вы не хотите инклюзивного отношения между группой 1 и 2,

\$\{([^:, ]*)(?::\(([^)]*)\))?\}

демонстрация

0

Другие решения

Я думаю, что ваш оригинальный подход \${(.*)} имеет небольшую проблему, которая заключается в том, что ваш шаблон сопоставления .* включает в себя } символ, которому вы не хотите соответствовать. Фактически, как только вы начинаете захват, это единственное, что вы не хотите сопоставлять, поэтому мы изменим:

.*      // match anything zero or more times

в

[^}]*   // match anything that isn't } zero or more times

Но вы хотите сопоставить все в фигурных скобках, если у него нет структуры some_underscored_words:(desired-text)в этом случае вы хотите соответствовать desired-text,

Я бы решил это, используя ? оператор, который вы помещаете после группы захвата, чтобы определить его как необязательный. ? является жадным, что означает, что он сначала попытается сопоставить, и только в случае неудачи он попытается обработать совпадения без дополнительного шаблона.

Чтобы думать об этом, полезно перефразировать то, что вы хотите, используя жадное мышление.

Вместо того чтобы говорить:

Я хочу захватить все, что находится внутри фигурных скобок, а также
захватить значение в скобках, если они существуют

Измените это на:

Я хочу захватить значение, которое вложено в скобках
внутри фигурных скобок, но если этого не существует, я просто буду
что бы ни было внутри брекетов.

Превратив это в регулярное выражение, я получаю это:

\${([a-z_]+:\()?([^\)}]*)

Разбивая это:

Начните с поиска уникального символа:

${

Попробуйте сопоставить с вложенным шаблоном:

([a-z_]+:\()?

Это соответствует any_underscored_lowercase_words один или несколько раз (+) с последующим :(

Теперь мы сопоставляем ноль или более букв, которые не являются ни одним из наших закрывающих тегов. ) или же }

([^\)}]*)

Будучи жадным, он идет прямо к вложенному шаблону. В противном случае совпадение сводится к захвату всего, что не является ни одним из закрывающих символов.

Один сценарий, который я могу придумать, где это не сработает, это:

${seems like a normal match) wait where did these letters go?}

Что даст вам «похоже на нормальный матч».

0

Чтобы построить лучший / самый быстрый шаблон, вы должны позволить механизму регулярных выражений работать как можно более жадным образом, что означает использование таких квантификаторов, как * а также + без запаздывания ?,

Следующий шаблон потребует первую группу захвата (выходной столбец [1]) и сделать вторую группу захвата необязательной (выходной столбец) [2]).

Предлагаемая модель: ~\$\{([^:}]+)(?::([^}]+))?~ (Образец Демо)

~             #starting pattern delimiter
\$\{          #match a dollar sign then opening curly bracket
(             #start Capture Group #1
[^:}]+      #match one or more non-colon, non-closing curly bracket characters
)             #end Capture Group #1
(?:           #start non-capturing group
:           #match a colon
(           #start Capture Group #2
[^}]+     #match one or more non-closing curly brackets
)           #end Capture Group #2
)?            #end non-capturing group and allow zero or one occurence of the group
~             #end pattern delimiter

Код: (демонстрация)

$string = '${first_name}, ${last_name}, ${create_date:(Y-m-d)}, ${submit_date:(Y-m-d)}';
var_export(preg_match_all('~\$\{([^:}]+)(?::([^}]+))?~', $string, $out, PREG_SET_ORDER) ? $out : 'fail');

Вы можете игнорировать [0] (полная строка) совпадение столбца. Вас интересуют только первая и вторая группы захвата.

Выход:

array (
0 =>
array (
0 => '${first_name',
1 => 'first_name',
),
1 =>
array (
0 => '${last_name',
1 => 'last_name',
),
2 =>
array (
0 => '${create_date:(Y-m-d)',
1 => 'create_date',
2 => '(Y-m-d)',
),
3 =>
array (
0 => '${submit_date:(Y-m-d)',
1 => 'submit_date',
2 => '(Y-m-d)',
),
)
0
По вопросам рекламы [email protected]