我有很多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可显示字符,即字母,数字,其他字符等。这就是为什么我使用了正则表达式{{1 }}。
但它似乎无法正常工作。
以下是我使用(.*)
进行的一些测试:
echo
结果:
$ echo "<td align=\"center\">#{i.m['Login']}</td>" | sed -e "s/#{i.m\['\(.*\)']}/\1/g"
确定
<td align="center">Login</td>
结果:
$ 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}" />
结果:
$ 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"
否
我正在使用Ubuntu 18.04。
答案 0 :(得分:1)
这里的问题是您没有考虑到正则表达式的贪婪性质。您需要防止正则表达式吞噬额外的'
:
sed -e“ s /#{i.m ['([^'] *)']} / \ 1 / g”
这也是David C. Rankin的解决方案起作用的原因。但是,他的正则表达式不必要地复杂。
答案 1 :(得分:1)
根据您的请求,并在我的评论和其他评论中指出,您绝对应该使用xmlstartlet
之类的适当XML解析器进行正确的XHTML解析。一个简单的正则表达式无法验证剩下的内容。
在您的示例中(仅举例来说),要替换保留LOGIN
,PASSWORD
和Submit
的文本,您可以使用以下正则表达式:
sed "s/[#][{]i[.]m[[][']\([^']*\)['][]][}]/\1/" <file
每当您必须匹配也可以作为正则表达式本身的一部分的字符时,有助于明确确保要匹配的字符被视为字符,而不是正则表达式的一部分。为此,您要使用字符类(例如[...]
,其中括号之间的字符是匹配的。(如果字符类中的第一个字符是'^'
,将反转匹配-即匹配除类中的所有内容之外的所有内容
有了这样的解释,正则表达式应该变得很清楚。正则表达式使用基本的替换形式:
sed "s/find/replace/" file
“查找” REGEX
[#]
-匹配井号[{]
-匹配左括号i
-匹配'i'
[.]
-明确匹配'.'
字符(而不是.
任何字符)m
-匹配'm'
[[]
-匹配左括号[']
-匹配单引号\(
-开始您的捕获组以捕获文本以重新插入作为后向引用 [^']*
-匹配不是单引号的零个或多个字符\)
-结束捕获组[']
-将单引号匹配为下一个字符[]]
-匹配右括号[}]
-匹配右括号。“替换” REGEX
作为查找捕获组的一部分(在\(....\)
之间)捕获的所有字符都可以用作替换的replace
部分中的后向引用。 find
部分中可以有多个捕获组,您在替换的替换部分将其引用为\1, \2, ...
,依此类推。在这里,在find部分中只有一个捕获组,因此匹配的任何东西都可以用作整个替换,例如
\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
之类的工具的原因)>