Регулярное выражение не выдает совпадения, когда содержит новую строку - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь проанализировать страницу https://extensions.typo3.org/extension/tt_news/ для номеров версий и соответствующих дат с помощью sed или grep.В частности, меня интересует следующий html-раздел:

            <tr>
                <td class="align-middle">
                    <strong>3.6.0</strong> /
                    <span class="ter-ext-state-beta">beta</span>
                    <br />
                    <small>
                        April 06, 2014
                    </small>
                </td>
                <td class="align-middle">
                    tt_news for TYPO3 4.5 - 6.2 (compatibility update)
                </td>
                <td class="align-middle">

                        <strong>4.5.0 - 6.2.99</strong>

                </td>
                <td class="align-middle">

                            <a class="btn btn-primary" title="Size: 2.58MB" href="/extension/download/tt_news/3.6.0/zip/">
                                <strong>
                                    Download ZIP Archive
                                </strong>
                            </a>

                </td>
            </tr>

. Я бы хотел получить из каждого из этих разделов версию (между тегом strong ) и дату (между тегом small ).Все мои попытки пока не увенчались успехом, и я могу сузить проблему до чего-то очень простого.Я протестировал следующее регулярное выражение, которое только пытается получить тег tr , за которым следуют пробелы и тег td на regex101.com, и там он работает отлично:

<tr>\s*<td

Это дает мне 5 матчей, что правильно.Следующий также отлично работает:

 <tr[^>]*>\s*<td

Он выдает 38 результатов, поскольку включает в себя те теги tr с атрибутом класса css.Однако ни с grep, ни с sed я не могу заставить это работать.Как только я включу \ s, совпадений больше нет.Вот как это выглядит:

cat tt_news_history | grep '<tr>\s*<td'

нет хитов.

cat tt_news_history | grep '<tr>'

6 хитов.

cat tt_news_history | grep '<tr[^>]*>'

много хитов (не в счет).То же самое с седом.Что я делаю неправильно?Почему я не могу использовать \ s?Спасибо за любую подсказку.

1 Ответ

0 голосов
/ 04 февраля 2019

Для GNU grep есть опция -z, которая заставляет \s соответствовать символам новой строки во вводе, например:

cat tt_news_history | grep -z '<tr>\s*<td'

Соответствующие фрагменты из информационной документации:

'- z' '--null-data' Входные и выходные данные обрабатываются как последовательности строк, каждая из которых заканчивается нулевым байтом (символ ASCII NUL) вместо новой строки.Как и опция '-Z' или '--null', эта опция может использоваться с такими командами, как 'sort -z', для обработки произвольных имен файлов.

(...)

Как мне сопоставить строки?

Стандартный grep не может этого сделать, так как он основан на строках.Поэтому простое использование класса символов '[: space:]' не соответствует символу новой строки, как вы могли бы ожидать.

С опцией GNU 'grep' '-z' ('--null-data') каждая входная «строка» завершается нулевым байтом;* примечание Другие параметры ::.Таким образом, вы можете сопоставлять символы новой строки во вводе, но обычно, если есть совпадение, выводится весь ввод, поэтому такое использование часто сочетается с опциями подавления вывода, такими как '-q', например:

printf 'foo \ nbar \ n '|grep -z -q 'foo [[: space:]] + bar'

Если этого недостаточно, вы можете преобразовать входные данные перед тем, как передать их в «grep», или обратиться к «awk», 'sed ',' perl 'или многие другие утилиты, предназначенные для работы через линии.

...