sed: вырезать строку в шаблоне - PullRequest
0 голосов
/ 20 сентября 2018

У меня есть много файлов XHTML, содержимое которых выглядит следующим образом:

<h:panelGroup rendered="#{not accessBean.isUserLoggedIn}">
    <h:form>
        <p:panel style="margin-top:10px">
            <table style="margin:10px">
                <tbody>
                    <tr>
                        <td align="center">#{i.m['Login']}</td>
                        <td align="center">
                            <h:inputText value="#{accessBean.login}" />
                        </td>
                    </tr>
                    <tr>
                        <td align="center">#{i.m['Password']}</td>
                        <td align="center">
                            <h:inputSecret value="#{accessBean.password}" />
                        </td>
                    </tr>
                </tbody>
            </table>
            <p:commandButton ajax="false" value="#{i.m['Submit']}" action="#{accessBean.login}" />
        </p:panel>
    </h:form>
</h:panelGroup>

Я хочу заменить каждое вхождение #{i.m['any-string>']} на any-string, т. Е. Вырезать строку в шаблоне.

Я создал следующую sed команду

sed -e "s/#{i.m\['\(.*\)']}/\1/g"

И для ее рекурсивного запуска в каталоге я мог бы выполнить

find . -iname '*.xhtml' -type f -exec sed -i -e "s/#{i.m\['\(.*\)']}/\1/g" {} \;

Здесьany-string может быть любым читаемым человеком HTML-отображаемым символом , т. Е. Алфавитом, числами, другими символами и т. Д. Вот почему я использовал регулярное выражение (.*).

Но этокажется, не работает идеально.

Вот некоторые тесты, которые я сделал, используя echo:

  1. $ echo "<td align=\"center\">#{i.m['Login']}</td>" | sed -e "s/#{i.m\['\(.*\)']}/\1/g"
    

    Результат:

    <td align="center">Login</td>
    

    ОК

  2. $ echo "<p:commandButton  ajax=\"false\" value=\"#{i.m['Submit']}\" action=\"#{accessBean.login}\" />" | sed -e "s/#{i.m\['\(.*\)']}/\1/g"
    

    Результат:

    <p:commandButton  ajax="false" value="Submit" action="#{accessBean.login}" />
    

    ОК

  3. $ echo "<p:commandButton ajax=\"false\" value=\"#{i.m['Submit']}\" action=\"#{accessBean.login}\" /> <td align=\"center\">#{i.m['Login']}</td>" | sed -e "s/#{i.m\['\(.*\)']}/\1/g"
    

    Результат:

    <p:commandButton ajax="false" value="Submit']}" action="#{accessBean.login}" /> <td align="center">#{i.m['Login</td>
    

    NOK

Я использую Ubuntu 18.04.

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

В соответствии с вашим запросом и, как отмечено в моем комментарии и комментариях других, для правильного синтаксического анализа XHTML вам определенно следует использовать правильный синтаксический анализатор XML, такой как xmlstartlet.Простое регулярное выражение не имеет проверки того, что осталось позади.

При этом, для вашего примера (только), чтобы заменить текст, оставляя LOGIN, PASSWORD и Submit, вы можете использовать следующеерегулярное выражение:

sed "s/[#][{]i[.]m[[][']\([^']*\)['][]][}]/\1/" <file

Всякий раз, когда вам нужно сопоставить символы, которые также могут быть частью самого регулярного выражения, это помогает явно убедиться, что символ, который вы хотите сопоставить, обрабатывается как символ, а не как часть регулярного выражения.выражение.Для этого вы используете класс символов (например, [...], где символы в скобках совпадают. (Если первый символ в классе символов '^', он будет инвертировать совпадение -- то есть совпадать со всем, кроме того, что находится в классе)

С этим объяснением, регулярное выражение должно стать ясным. Регулярное выражение использует базовую форму замены:

sed "s/find/replace/" file

Поиск'REGEX

  • [#] - сопоставить знак фунта
  • [{] - сопоставить открывающую скобку
  • i - сопоставить 'i'
  • [.] - явно соответствует символу '.' (вместо . любой символ)
  • m - соответствует 'm'
  • [[] - сопоставить открывающую скобку
  • ['] - сопоставить одинарную кавычку
  • \( - начать захват группы, чтобы перехватить текст для повторной вставки в качестве обратной ссылки
  • [^']* - совпадение ноль или более символов, которые не являются одинарными кавычками
  • \) - завершить захватгруппа
  • ['] - сопоставить одинарную кавычку как следующий символ
  • []] - сопоставить с закрывающей скобкой
  • [}] - сопоставить с закрывающей скобкой.

REGEX * replace '1073 *

' replace 'Все символы, захваченные как часть группы захвата поиска (между \(....\)), доступны для использования в качестве заднегоссылка в replace части замещения.Вы можете иметь более одной группы захвата в части find, которую вы указали в замещающей части замещения как \1, \2, ... и так далее.Здесь у вас есть только одна группа захвата в части поиска, поэтому все, что было найдено, можно использовать в качестве всей замены, например,

  • \1 - чтобы заменить весь беспорядок только текстом, который былзахвачено с помощью [^']*

Пример использования / Вывод

Для использования с вашим примером оно правильно оставит Login, Password и Submit как указано в вашем вопросе, например,

sed "s/[#][{]i[.]m[[][']\([^']*\)['][]][}]/\1/" file
<h:panelGroup rendered="#{not accessBean.isUserLoggedIn}">
    <h:form>
        <p:panel style="margin-top:10px">
            <table style="margin:10px">
                <tbody>
                    <tr>
                        <td align="center">Login</td>
                        <td align="center">
                            <h:inputText value="#{accessBean.login}" />
                        </td>
                    </tr>
                    <tr>
                        <td align="center">Password</td>
                        <td align="center">
                            <h:inputSecret value="#{accessBean.password}" />
                        </td>
                    </tr>
                </tbody>
            </table>
            <p:commandButton ajax="false" value="Submit" action="#{accessBean.login}" />
        </p:panel>
    </h:form>
</h:panelGroup>

Опять же, в качестве отказа от ответственности и просто здравого смысла, не анализируйте X / HTML с регулярным выражением, используйте подходящий инструмент, такой как xmlstartlet.Не анализируйте JSON с регулярным выражением, используйте подходящие инструменты для работы, такие как jq - вы получите дрейф.(но для этого ограниченного примера регулярное выражение работает хорошо, но оно хрупкое, если что-то во входных данных изменится, оно сломается - вот почему у нас есть такие инструменты, как xmlstartlet и jq)

0 голосов
/ 20 сентября 2018

Проблема здесь в том, что вы не учитываете жадную природу регулярных выражений.Вам нужно не допустить, чтобы ваше регулярное выражение сожрало лишние ' s:

sed -e "s / # {im ['([^'] *) ']} / \ 1 / g"

Это также причина, по которой работает решение Дэвида К. Ранкина.Однако его регулярные выражения излишне сложны.

...