regex — PHP: токенизация с использованием регулярных выражений (в основном там)

Я хочу токенизировать строки форматирования (очень похоже на printf), и я думаю, что мне не хватает только немного:

  • % [число] [одна буква ctYymd] становится токеном²
  • $ 1 … $ 10 должен стать токеном
  • все остальное (обычный текст) становится токеном.

Я довольно далеко симулятор regExp. Это выглядит так:

«Update: теперь используется # вместо%. (Меньше проблем с параметрами командной строки Windows)

введите описание изображения здесь

Это не страшно, если вы сосредоточитесь на трех частях, соединенных трубами (как-либо), так что в основном это всего три матча. Так как я хочу соответствовать от начала до конца, я завернул вещи в /^...%/ и окружен несоответствующей группой (?:... это может повторяться 1 или более раз:

$exp = '/^(?:(%\\d*[ctYymd]+)|([^$%]+)|(\\$\\d))+$/';

Тем не менее мой источник не доставляет:

$exp = '/^(?:(%\\d*[ctYymd]+)|([^$%]+)|(\\$\\d))+$/';
echo "expression: $exp \n";

$tests = [
'###%04d_Ball0n%02d$1',
'%03d_Ball0n%02x$1%03d_Ball0n%02d$1',
'%3d_Ball0n%02d',
];

foreach ( $tests as $test )
{
echo "teststring: $test\n";
if( preg_match( $exp, $test, $tokens) )
{
array_shift($tokens);
foreach ( $tokens as $token )
echo "\t\t'$token'\n";
}
else
echo "not valid.";
} // foreach

Я получаю результаты, но: Матчи не в порядке. Первый% [число] [буква] никогда не совпадает, поэтому другие совпадают с двойным:

expression: /^((%\d*[ctYymd]+)|([^$%]+)|(\$\d))+$/
teststring: ###%04d_Ball0n%02d$1
'$1'
'%02d'
'_Ball0n'
'$1'
teststring: %03d_Ball0n%02x$1%03d_Ball0n%02d$1
not valid.teststring: %3d_Ball0n%02d
'%02d'
'%02d'
'_Ball0n'
teststring: %d_foobardoo
'_foobardoo'
'%d'
'_foobardoo'
teststring: Ball0n%02dHamburg%d
'%d'
'%d'
'Hamburg'

5

Решение

Решение (под редакцией OP): я использую два небольших варианта (только в отношении «обтекания»): сначала для проверки, затем для токенизации:

#\d*[ctYymd]+|\$\d+|[^#\$]+

RegEx Demo

Код:

$core = '#\d*[ctYymd]+|\$\d+|[^#\$]+';
$expValidate = '/^('.$core.')+$/m';
$expTokenize = '/('.$core.')/m';

$tests = [
'#3d-',
'#3d-ABC',
'***#04d_Ball0n#02d$1',
'#03d_Ball0n#02x$AwrongDollar',
'#3d_Ball0n#02d',
'Badstring#02xWrongLetterX'
];

foreach ( $tests as $test )
{
echo "teststring: [$test]\n";

if( ! preg_match_all( $expValidate, $test) )
{
echo "not valid.\n";
continue;
}
if( preg_match_all( $expTokenize, $test, $tokens) ) {
foreach ( $tokens[0] as $token )
echo "\t\t'$token'\n";
}

} // foreach

Выход:

teststring: [#3d-]
'#3d'
'-'
teststring: [#3d-ABC]
'#3d'
'-ABC'
teststring: [***#04d_Ball0n#02d$1]
'***'
'#04d'
'_Ball0n'
'#02d'
'$1'
teststring: [#03d_Ball0n#02x$AwrongDollar]
not valid.
teststring: [#3d_Ball0n#02d]
'#3d'
'_Ball0n'
'#02d'
teststring: [Badstring#02xWrongLetterX]
not valid.
2

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

Других решений пока нет …

По вопросам рекламы [email protected]