sed:在模式中剪切字符串

sed:在模式中剪切字符串,sed,Sed,我有许多XHTML文件,其内容如下: <h:panelGroup rendered="#{not accessBean.isUserLoggedIn}"> <h:form> <p:panel style="margin-top:10px"> <table style="margin:10px"> <tbody> <

我有许多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>
在我可以执行的目录中递归地运行它

find . -iname '*.xhtml' -type f -exec sed -i -e "s/#{i.m\['\(.*\)']}/\1/g" {} \;
在这里,
任何字符串
可以是任何人类可读的HTML可显示字符,即字母表、数字、其他字符等。这就是为什么我使用regex
(*)

但它似乎工作得并不完美

下面是我使用echo进行的一些测试:

  • $echo“{i.m['Login']}”sed-e“s/{i.m\['(.*\')]}/\1/g”
    
    结果:

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

  • $echo”“| sed-e”s/#{i.m\['(.*\')]}/\1/g”
    
    结果:

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

  • $echo“{i.m['Login']}”sed-e“s/{i.m\['(.*\')]}/\1/g”
    
    结果:

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


  • 我使用的是Ubuntu 18.04。

    这里的问题是你没有考虑到regexp的贪婪本质。你需要防止你的regexp占用额外的
    s:

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


    这也是David C.Rankin的解决方案起作用的原因。然而,他的regexp不必要地复杂。

    根据您的请求,正如我的评论和其他人的评论所指出的,您绝对应该使用适当的XML解析器,如
    xmlstartet
    进行适当的XHTML解析。简单的regex不会验证遗留下来的内容

    也就是说,对于您的示例(仅),要替换离开
    LOGIN
    PASSWORD
    Submit
    的文本,您可以使用以下正则表达式:

    sed "s/[#][{]i[.]m[[][']\([^']*\)['][]][}]/\1/" <file
    
    查找正则表达式

    • [#]
      -匹配英镑符号
    • [{]
      -匹配开口大括号
    • i
      -匹配
      'i'
    • [.]
      -显式匹配
      字符(而不是
      任何字符)
    • m
      -匹配
      'm'
    • [[]
      -匹配开口括号
    • [']
      -匹配单引号
    • \(
      -开始您的捕获组捕获要重新插入的文本作为反向引用
    • [^']*
      -匹配非单引号的零个或多个字符
    • \)
      -结束您的捕获组
    • [']
      -将单个引号匹配为下一个字符
    • []]
      -匹配右括号
    • [}]
      -匹配右大括号
    替换正则表达式

    作为查找捕获组的一部分捕获的所有字符(在
    \(....\)
    之间),可用作替换的
    replace
    部分中的反向引用。在
    find
    部分中可以有多个捕获组,您可以在替换的replace部分中将其引用为
    \1、\2、…
    等等。在这里,查找部分中只有一个捕获组,所以不管怎样已匹配可以用作整个替换,例如

    • \1
      -用
      [^']*
    示例使用/输出

    为了与您的示例一起使用,它将正确地保留您问题中所示的
    登录
    密码
    提交
    ,例如

    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>
    
    sed“s/[\\][{]i[.]m[[[]]]\([^']*\)['][]][}]/\1/”文件
    登录
    密码
    

    同样,作为免责声明和良好的常识,不要用正则表达式解析X/HTML,使用适当的工具,如
    xmlstartet
    。不要用正则表达式解析JSON,使用适当的工具来完成工作,如
    jq
    ——你明白了。(但对于这个有限的例子,正则表达式工作得很好,但它很脆弱,如果输入中有任何变化,它就会崩溃——这就是为什么我们有
    xmlstartet
    jq
    )等工具的原因。

    首先选择正确的工具。我建议使用XML/HTML解析器(例如xmlstarlet)@Cyrus,谢谢你的回答。我刚刚更新了问题并删除了部分内容。虽然你肯定应该使用适当的XML解析器,比如
    xmlstartet
    ,来替换离开
    LOGIN
    PASSWORD
    Submit
    的文本,但你可以使用以下正则表达式:
    sed“s/[#][{]I[.]m[[][']\([^']*\)['][]][}]/\1/“@DavidC.Rankin,请您将您的评论作为答案发布,以便我可以接受。您的解决方案非常有效。另外,如果您能解释一下这个表达方式,那将非常好。谢谢:-)