Sed script for find/replace inside .jsp files. (from Struts to JSTL EL syntax)
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:
${ ifram开发者_高级运维esrcUrl }
${ 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?
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 }
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.
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).
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
精彩评论