用于在 .jsp 文件内查找/替换的 Sed 脚本。 (从 Struts 到 JSTL EL 语法)

发布于 2024-08-15 11:50:57 字数 597 浏览 4 评论 0原文

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

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

或类似内容。 nameproperty 值可以不同。 propertyfilter 属性是可选的。单引号 ' 和双引号 " 都会出现。

sed 命令必须是双头的:我想首先运行一个命令来查看它找到的内容。 然后我想运行下一个命令来进行实际的替换。字符串应替换为:

${ iframesrcUrl }
${ currentPage.title }

快速 grep 显示我的项目中有 68 次出现: grep '

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

I want a sed script that I can use for 1) finding instances, and 2) printing this string:

<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.

The sed command must be two headed: I want first to run one command to see what it finds.
Then I want to run the next command to make the actual replacements. The strings should be replaced with:

${ iframesrcUrl }
${ currentPage.title }

A quick grep shows there are 68 occurences in my project: grep '<bean:write name=' **/* |wc -l

What would be the easiest way to solve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

苏别ゝ 2024-08-22 11:50:57

从部分涵盖我的问题的其他答案中学习后,我最终得到以下结果。

(我打赌它可以变得更短,但它有效)我尝试找到每一个出现的结构,例如

#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:]] 与点 . 不匹配。

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

Having learned from the other answers that partially covered my question, i ended up with the following.

(I bet it can be made shorter but it works)my try to find every occurence of constructions like

#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 

A few lessons learned:

  • $ is reserved from the command line, so I had to escape the $ sign in lines where the sed expression is within double-quotes
  • \w did not work for matching any word character. So I had to substitute with [[:alpha:]]
  • Substitutions in any file in any directory (*/* **/*) is a no-go for hidden system files, binary files like images, etc. I had to focus on only .jsp and .inc files for my project: *.jsp **/*.jsp **/*.inc

One more word of caution: I did this on a project to move it away from old-school struts style. If you are in a similar situation be careful to review any edits manually afterwards.

Script shortcomings:
For various reasons, the following examples were not found with the script above:

<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 failed because [[:alpha:]] did not match - (and there are also some with underscores).

#2 is the same: [[:alpha:]] does not match a dot ..

#4 concatenates strings inside parameter name. I could write a script to find them , but there are only four occurences in the project. The big question is what it should be replaced with. I suspect inline java does not work. and I suspect I cannot just write ${ 'optTextUrl' + id }

夜血缘 2024-08-22 11:50:57

我将在这里离开你的 grep 正则表达式

1)打印它找到的内容

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

2)替换它找到的内容

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

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

#!/bin/bash

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

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

I'm going off of your grep regex here

1) Print what it finds

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

2) Replace what it finds

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

Looking further at your question, I see you appear to have Bash4 with globstar on (due to the **/* glob). If you want these sed scripts to run on each file recursively I would suggest:

#!/bin/bash

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

For the replacement sed script, just add -i to do an in-place edit. Note that this requires GNU sed to work. If you don't have GNU sed, you will have to redirect the output to a temp file.

老街孤人 2024-08-22 11:50:57

假设您有一个类似的文件,

<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>

假设我们要替换 foo 带有 SPAMbar 带有 EGGS。然后这个命令就会做到这一点(为了可读性而分行):

$ 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 语法来选择要替换的元素(在第一种情况下,它是属于任何 cname 属性> 标记并且等于 foo)。 xmlstarleted 子命令允许各种转换,替换(更新)元素只是其中之一。

在实际示例中,您还需要指定 bean 工作空间,即向

 -N bean=urn:...

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

Assuming that you have a file like

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

you can do replacements with this sed command (using GNU sed):

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

which produces:

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

Is it what you need? Or do you want to replace attributes' values? Or do you want to put your substitution text into these tags?

To find and edit all files in-place (attention! changes your files, please test without -i before use, put your file mask instead of '*.jsp'):

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

UPDATE

To replace attribute values, not the lines of file themselves, I would strongly recommend using xmlstarlet instead of sed/awk. It is much more reliable and flexible. I cannot post solution exactly for your case, because xmlstarlet needs a complete (valid) file to process, but this is an idea:

Given a file:

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

Let say we want replace foo with SPAM and bar with EGGS. Then this command will do it (splitted lines for readability):

$ 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>

I used XPath syntax to select an element to replace (in the first case it is name attribute which belongs to any c tag and is equal to foo). ed subcommand of xmlstarlet allows various transformations, replacing (updating) an element is just on of them.

In real-life examples you will need to specify also bean workspace, i.e. add something like

 -N bean=urn:...

to the list of xmlstarlet's options. You can find the correct URI in the first lines of your .jsp file (I don't have any to look at).

南七夏 2024-08-22 11:50:57

目前尚不清楚您的输出可能是什么。只是猜测,直到您提供更清晰的示例输入和输出

awk '/bean:write name/{
    $0="${ iframesrcUrl }\n${ currentPage.title }"
}{print}' file

its not exactly clear what your output might be. just a guess until you provide more clear sample inputs and output

awk '/bean:write name/{
    $0="${ iframesrcUrl }\n${ currentPage.title }"
}{print}' file
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文