Регулярное выражение для разбора курсивного текста?

Предположим, у меня есть следующий текст:

__This_is__ a __test__

Использование двух подчеркиваний для обозначения курсива. Так что я ожидаю This_is а также test быть выделенным курсивом. Логика подсказывает, что любой текст между двумя последовательными двойными подчеркиваниями должен быть выделен курсивом, включая любое другое количество подчеркиваний, которые могут быть там. У меня есть:

__([^_]+)__

Что эквивалентно "не двум последовательным подчеркиваниям" в группе 1? Благодарю.

2 ответа

Решение

Вариант будет соответствовать двум подчеркиваниям:

__

Затем сделайте отрицательный взгляд вперед, чтобы увидеть, нет ли двух подчеркиваний впереди текущей позиции:

__(?!__)

если это не так, сопоставьте любой символ:

__(?!__). 

и повторите предыдущий один или несколько раз:

__((?!__).)+

и, наконец, сопоставьте еще два подчеркивания:

__((?!__).)+__

что является окончательным решением.

Немного демо:

<?php
$text = '__This_is__ a __test__';
preg_match_all('/__(?:(?!__).)+__/', $text, $matches);
print_r($matches);
?>

производит:

Array
(
    [0] => Array
        (
            [0] => __This_is__
            [1] => __test__
        )

)

как можно увидеть на Ideone.

РЕДАКТИРОВАТЬ

Обратите внимание, что в моей демонстрации я использовал группу без захвата, иначе результат выглядел бы так:

Array
(
    [0] => Array
        (
            [0] => __This_is__
            [1] => __test__
        )

    [1] => Array
        (
            [0] => s
            [1] => t
        )

)

то есть последний символ соответствует ((?!__).) был бы захвачен в группе 1.

Подробнее о группах см.: http://www.regular-expressions.info/brackets.html

$text = '__This_is__ a __test__';
preg_match_all('/(__([\w]+)__)/', $text, $matches);
print_r($matches);

http://ideone.com/uHJCC

Другие вопросы по тегам