RegEx и HTML: Как сопоставить элемент «foo», который содержит как минимум два других элемента «bar»?(негативный взгляд в будущее) - PullRequest
0 голосов
/ 25 ноября 2018

Мне нравится соответствовать элементу "table", который имеет класс "zot" и содержит как минимум два элемента "td".Например, таблица, которая содержит только «th», но не содержит «td», не должна совпадать.

Я безуспешно пробовал следующее выражение:

<table class="zot">([\S\s]*?(?!\/table>)<td){2,}

То же выражение в более читаемом свободном интервалеСинтаксис:

<table class="zot"> # literal
(                   # begin of group
[\S\s]              # non whitespace or whitespace
*                   # quantifier
?                   # greediness modificator
(?!\/table>)        # negative look ahead assertion with the literal "/table>" 
<td                 # literal
)                   # end of group
{2,}                # quantifier

Возможно, мое понимание негативного взгляда неверно.

Я создал кодовое перо для случая: https://regexr.com/43mmh

В чем моя ошибка,пожалуйста?Спасибо.

Ниже вы найдете мой HTML-код для теста (такой же, как в кодовой ручке):

<table class="zot">
        <tr>
            <th>a</th>
            <th>b</th>
        </tr>
        <tr>
            <td>c</td>
            <td>d</td>
        </tr>
</table>
<p>Lorem</p>
<table class="zot">
        <tr>
            <th>e</th>
        </tr>
        <tr>
            <td>f</td>
        </tr>
</table>
<table class="zot">
        <tr>
            <th>g</th>
            <th>h</th>
        </tr>
        <tr>
            <td>i</td>
            <td>j</td>
        </tr>
</table>

Какие совпадения я хочу получить?

<table class="zot">
    <tr>
        <th>a</th>
        <th>b</th>
    </tr>
    <tr>
        <td>c</td>
        <td

и

<table class="zot">
    <tr>
        <th>g</th>
        <th>h</th>
    </tr>
    <tr>
        <td>i</td>
        <td

Ответы [ 2 ]

0 голосов
/ 25 ноября 2018

Я полностью переписал свой ответ, теперь вы получите 1 match per table с более чем одной ячейкой таблицы.

Регулярное выражение :

<table class="zot">(?:(?:[\S\s](?!\/table>))*?<td){2,}[\S\s]*?<\/table>

Объяснение:

<table class="zot"> соответствует литеральной строке <table class="zot">.

(?: создает группу без захвата.

(?: создает незахват группы.

[\S\s] совпадает с пробелом и не пробелом (всем) один раз.

(?!\/table>) создает негативный прогноз на будущее: '/table'.

*? Эта группа соответствует нулю или более раз - не жадный.

<td соответствует литеральной строке <td.

{2,} Внешняя группа соответствует 2 или болеераз.

[\S\s]*? соответствует любому нулю или более раз.

<\/table> соответствует буквенной строке <\/table>

Вам необходимо установить флаг 'global'.

Теперь вы получаете по одному совпадению на таблицу, содержащую не менее 2 table cells.

Вы можете проверить это Regexr или Здесь

0 голосов
/ 25 ноября 2018

Если вы хотите, чтобы foo предшествовал bar, вы можете использовать

<table class="zot">((?!\/table>).)+foo(?1)+bar(?1)+<\/table>

https://regexr.com/43nkb

Общая идея - повторить любой символ, который не является/ in /table>, соответствует foo, повторите предыдущий шаблон снова, соответствует bar, снова соответствует предыдущему шаблону и, наконец, соответствует тегу конечной таблицы.

Обратите внимание на флаг sи использование синтаксиса (?1), который значительно облегчает чтение регулярных выражений.Без этого вам придется использовать [\s\S] вместо . и набирать первый подшаблон вручную вместо (?1) s, например

<table class="zot">(?:(?!\/table>)[\s\S])+foo(?:(?!\/table>)[\s\S])+bar(?:(?!\/table>)[\s\S])+<\/table>

При этом, если это вообще возможнов любой среде, которую вы используете, было бы более элегантно использовать правильный анализатор HTML.

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