0

我想要一个可用于 1) 查找实例和 2) 打印此字符串的 sed 脚本:

<bean:write name='iframesrcUrl'/> 
<bean:write name="iframesrcUrl"/>
<bean:write name="currentPage" property="title" filter="false"/>

或类似的。name并且property值可以不同。propertyfilter属性是可选的。单引号'和双引号"都会出现。

sed 命令必须有两个标题:我想首先运行一个命令来查看它找到了什么。然后我想运行下一个命令来进行实际的替换。字符串应替换为:

${ iframesrcUrl }
${ currentPage.title }

快速 grep 显示我的项目中有 68 次出现:grep '<bean:write name=' **/* |wc -l

解决这个问题的最简单方法是什么?

4

4 回答 4

1

从部分涵盖我的问题的其他答案中学习后,我得出了以下结论。

(我打赌它可以做得更短,但它有效)我试图找到每一次出现的结构,比如

#my try to find every occurence of constructions like 
# <bean:write name='iframesrcUrl'/> 
# <bean:write name="iframesrcUrl"/>
# <bean:write name="currentPage" property="title" filter="false"/>
# 
# or similar. name and property values can differ. property and filter attributes are optional. 
# Both single quotes ' and double quotes " occur.
#
# cd jahia_virk/tomcat/webapps/ROOT/jsp/jahia/templates/virk/virk.dk


# Printing occurences:
# =====================
sed -nE \
-e '/<bean:write name="([[:alpha:]]+)"( property="([[:alpha:]]+)")( filter="false")?\/>/p' \
-e "/<bean:write name='([[:alpha:]]+)'( property='([[:alpha:]]+)')( filter='false')?\/>/p" \
-e '/<bean:write name="([[:alpha:]]+)"\/>/p' \
-e "/<bean:write name='([[:alpha:]]+)'\/>/p" \
*.jsp **/*.jsp **/*.inc  


# Replacing occurences:
# =====================
sed -E -i .bak \
-e 's/<bean:write name="([[:alpha:]]+)"( property="([[:alpha:]]+)")( filter="false")?\/>/${ \1.\3 }/g' \
-e "s/<bean:write name='([[:alpha:]]+)'( property='([[:alpha:]]+)')( filter='false')?\/>/\${ \1.\3 }/g" \
-e 's/<bean:write name="([[:alpha:]]+)"\/>/${ \1 }/g' \
-e "s/<bean:write name='([[:alpha:]]+)'\/>/\${ \1 }/g" \
*.jsp **/*.jsp **/*.inc 

一些经验教训:

  • $是从命令行保留的,所以我不得不转义$sed 表达式在双引号内的符号行
  • \w不适用于匹配任何单词字符。所以我不得不用[[:alpha:]]
  • 任何目录 ( ) 中的任何文件中的替换*/* **/*对于隐藏的系统文件、图像等二进制文件等都是不允许的。我必须只关注项目的 .jsp 和 .inc 文件:*.jsp **/*.jsp **/*.inc

再提醒一句:我在一个项目中这样做是为了摆脱老式的 struts 风格。如果您处于类似情况,请小心之后手动查看任何编辑。

脚本缺点: 由于种种原因,上面的脚本没有找到以下示例:

<bean:write name='scriptEditor-Url'/>    
<bean:write name='currentSite' property='homePage.url'/>
<bean:write name="portlet" property="value" filter="false" />
<bean:write name='<%= "optTextUrl" + id %>'/>

#1 失败,因为[[:alpha:]]不匹配-(也有一些带有下划线)。

#2 相同:[[:alpha:]]不匹配 dot .

#4 在参数名称中连接字符串。我可以编写一个脚本来找到它们,但项目中只有四个出现。最大的问题是应该用什么代替它。我怀疑内联 java 不起作用。我怀疑我不能只写${ 'optTextUrl' + id }

于 2009-12-22T10:54:30.103 回答
0

我要离开你的 grep 正则表达式

1)打印它找到的东西

sed '/<bean:write name=/!d'

2)替换它找到的东西

sed '/<bean:write name=/s/^.*$/${ iframesrcUrl }\n${ currentPage.title }/'

进一步查看您的问题,我发现您似乎有带有 globstar 的 Bash4(由于 **/* glob)。如果您希望这些 sed 脚本以递归方式在每个文件上运行,我建议:

#!/bin/bash

for file in **/*; do
    <sed one-liner here> "$file"
done

对于替换 sed 脚本,只需添加-i以进行就地编辑。请注意,这需要 GNU sed 才能工作。如果您没有 GNU sed,则必须将输出重定向到临时文件。

于 2009-12-22T09:29:30.493 回答
0

它并不完全清楚你的输出可能是什么。只是猜测,直到您提供更清晰的示例输入和输出

awk '/bean:write name/{
    $0="${ iframesrcUrl }\n${ currentPage.title }"
}{print}' file
于 2009-12-22T10:04:31.587 回答
0

假设你有一个像

<root>
<bean:write name='iframesrcUrl'/> 
<bean:write name="iframesrcUrl"/>
<bean:write name="currentPage" property="title" filter="false"/>
<foo><bar/></foo>
</root>

您可以使用此命令进行替换sed(使用 GNU sed):

 sed "s/<bean:write name=[\'\"]\?iframesrcUrl[\'\"]\?\/>/\${ iframesrcUrl }/g; \
      s/<bean:write name=[\'\"]\?currentPage[\'\"]\?.*\/>/\${ currentPage.title }/g;" \
     input.xml

产生:

<root>
${ iframesrcUrl } 
${ iframesrcUrl }
${ currentPage.title }
<foo><bar/></foo>
</root>

这是你需要的吗?或者你想替换属性的值?或者您想将替换文本放入这些标签中吗?

要在原地查找和编辑所有文件(注意!更改您的文件,请-i在使用前进行测试,使用您的文件掩码而不是 '*.jsp'):

find . -type f -name '*.jsp' -print0 | xargs -0 sed -i "..."

更新

要替换属性值,而不是文件本身的行,我强烈建议使用xmlstarlet而不是sed/ awk。它更加可靠和灵活。我不能完全针对您的情况发布解决方案,因为xmlstarlet需要一个完整(有效)的文件来处理,但这是一个想法:

给定一个文件:

<a>
   <b>
      <c name="foo"/>
      <c name="bar"/>
   </b>
</a>

假设我们要替换fooSPAM和。然后此命令将执行此操作(为了便于阅读而拆分行):barEGGS

$ printf '<a><b><c name="foo"/><c name="bar"/></b></a>' | \
  xmlstarlet ed --update "//c[@name='foo']/@name" -v SPAM \
                --update "//c[@name='bar']/@name" -v EGGS
<?xml version="1.0"?>
<a>
  <b>
    <c name="SPAM"/>
    <c name="EGGS"/>
  </b>
</a>

我使用 XPath 语法来选择要替换的元素(在第一种情况下,它是name属于任何c标记的属性,并且等于foo)。ed的子命令xmlstarlet允许各种转换,替换(更新)元素就在其中。

在现实生活中的示例中,您还需要指定bean工作区,即添加类似

 -N bean=urn:...

xmlstarlet的选项列表。您可以在 .jsp 文件的第一行中找到正确的 URI(我没有任何可查看的内容)。

于 2009-12-22T13:02:17.640 回答