О вашем строковом регулярном выражении: вы говорите, что это строка тогда и только тогда, когда ей предшествует
символ пробела или (
, за которым сразу следует ,
или )
.
Иглы говорят, что это не правильно. Вы пропустите строки вроде:
$s = "123"; // ends with a ;
$s = "ab\"cd"; // contains an escaped double quote
$t = 'efg' ; // is surrounded by single quotes
назвать только три (их еще много, а как насчет 'here-docs'?).
Чтобы исправить ситуацию, описанную выше, попробуйте что-то вроде этого:
$line = 's = "123"; t = "ab\\\\\\"cd"; u = \'efg\' ; v = \'ef\\\'g\' ';
echo $line . "\n";
echo preg_replace('/((["\'])(?:\\\\.|(?:(?!\2).|[^\\\\"\'\r\n]))*\2)/', '<span class="string">$1</span>', $line);
/* output:
s = "123"; t = "ab\\\"cd"; u = 'efg' ; v = 'ef\'g'
s = <span class="string">"123"</span>; t = <span class="string">"ab\\\"cd"</span>; u = <span class="string">'efg'</span> ; v = <span class="string">'ef\'g'</span>
*/
Краткое объяснение:
( # start group 1
(["\']) # match a single- or double quote and store it in group 2
(?: # start non-matching group 1
\\\\. # match a double quote followed by any character (except line breaks)
| # OR
(?: # start non-matching group 2
(?!\2). # a character other than what is captured in group 2
| # OR
[^\\\\"\'\r\n] # any character except a backslash, double quote, single quote or line breaks
) # end non-matching group 2
)* # end non-matching group 1 and match it zero or more times
\2 # the quote captured in group 2
) # end group 1
Затем несколько комментариев о вашем втором регулярном выражении: сначала вы пытаетесь найти ноль или более
символы пробела. Это может быть безопасно опущено, потому что если не существует пробелов
у тебя все равно будет матч. Вы можете использовать \b
(границу слова) перед соответствием
имя функции Также (?:[a-z]|[0-9]|_)
можно заменить на (?:[a-z0-9_])
. А также
эта часть вашего регулярного выражения: (@?|!?[a-z]+(?:[a-z]|[0-9]|_)*)
, что совпадает с:
(
@?
|
!?
[a-z]+
(?:
[a-z]
|
[0-9]
|
_
)*
)
только лучше с отступом, чтобы увидеть, что на самом деле делает. Если вы посмотрите внимательно, вы будете
видно, что оно будет соответствовать @?
, а поскольку @
становится необязательным для ?
, то
часть вашего регулярного выражения также будет соответствовать пустой строке. Нет, что ты ожидал, а?
После этого я должен признаться, что перестал смотреть на это регулярное выражение, лучше брось его
прочь.
Попробуйте что-то вроде этого, чтобы соответствовать именам функций:
'/\b[a-z_][a-z0-9_]*(?=\s*\()/i'
Что означает:
\b # a word boundary (the space between \w and \W)
[a-z_] # a letter or an underscore
[a-z0-9_]* # a letter, digit or an underscore, zero or more times
(?= # start positive look ahead
\s* # zero ore more white space characters
\( # an opening parenthesis
) # end positive look ahead
Последний не тестируется, я оставляю это для вас. Также обратите внимание, что я очень мало знаю PHP, поэтому я могу его упростить, и в этом случае будет полезно, если вы предоставите пару примеров фрагментов кода, которые вы хотите сопоставить в качестве функций.
Кроме того, предостережение: парсинг кода с использованием регулярных выражений может быть сложным, но если
вы используете его только для выделения небольших фрагментов кода, вы
все должно быть в порядке. Когда исходные файлы становятся больше, вы можете увидеть падение
производительность, и вы должны сделать некоторые части вашего регулярного выражения "притяжательным" , который будет
значительно увеличьте время выполнения вашего соответствия (особенно для больших исходных файлов).
Наконец, вы, вероятно, изобретаете велосипед. Существуют многочисленные (хорошо протестированные) средства подсветки кода, которые вы можете использовать. Я подозреваю, что вы уже знаете это, но я подумал, что все же стоит упомянуть.
К вашему сведению, у меня был хороший опыт с этим: http://shjs.sourceforge.net/doc/documentation.html