Preg совпадение по коду отображения php - PullRequest
0 голосов
/ 23 октября 2009

Привет всем, я в настоящее время пишу функцию "Показать код php" (вывод можно увидеть на http://www.actwebdesigns.co.uk/web-design-mansfield/php-functions/display-code-function.php)

У меня проблемы с цветовой схемой, которая выполняется с помощью регулярного выражения. 2 в частности:

строка:

$line = preg_replace("#(\s|\()(\"[^\"]*\")(\,|\))#is", "\\1<span class=\"string\">\\2</span>\\3", $line);

(и пытается)

#\"((?!(?:\"\s*;)|(?:\"\s*,)).)*#is

и функции:

$line = preg_replace("#(\s*)(@?|!?[a-z]+(?:[a-z]|[0-9]|_)*)(\s*)\(([^\)]*)\)#is", "\\1<span class=\"function\">\\2\\3</span>(\\4)", $line);

(если функция находится внутри функции, она не меняет цвет.

Ответы [ 2 ]

0 голосов
/ 23 октября 2009

О вашем строковом регулярном выражении: вы говорите, что это строка тогда и только тогда, когда ей предшествует символ пробела или (, за которым сразу следует , или ). Иглы говорят, что это не правильно. Вы пропустите строки вроде:

$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

0 голосов
/ 23 октября 2009

почему так сложно? Используйте hightlight_string(). ... и буферизацию вывода и ini_set(), если вам нужно изменить его вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...