Reputation: 504
I want to match multiple patterns in xml files, copy and modify the matched lines. The xml format is in a multi-line pattern,
<security-role-assignment>
...
</security-role-assignment>
which are on separate lines (not on the same line). I want to duplicate the block that contains the string "beanA_users" within the multi-line pattern, then replace the duplicated block with:
s#beanA_users#beanB_users#
s#runas_a#runas_b#
My environment have awk, sed, grep, but not xml_grep nor xmlstarlet.
awk -V
GNU Awk 5.0.0, API: 2.0 (GNU MPFR 4.1.0, GNU MP 6.2.1).
in.xml
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
out.xml
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanB_users</role-name>
<principal-name>runas_b</principal-name>
</security-role-assignment>
in2.xml
<security-role-assignment>
<role-name>beanXYZ_users</role-name>
<principal-name>runas_test</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanC_users</role-name>
<principal-name>runas_c</principal-name>
</security-role-assignment>
out2.xml
<security-role-assignment>
<role-name>beanXYZ_users</role-name>
<principal-name>runas_test</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanB_users</role-name>
<principal-name>runas_b</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanC_users</role-name>
<principal-name>runas_c</principal-name>
</security-role-assignment>
e.g.
awk -f test.awk in.xml > out.xml
awk -f test.awk in2.xml > out2.xml
test.awk (this is my best version so far, still need a lot of work)
/<security-role-assignment>/ {
xmlbuf = xmlbuf $0 ORS
gsub(/beanA_users/,"beanB_users",xmlbuf)
gsub(/runas_a/,"runas_b",xmlbuf)
print; next
}
xmlbuf!="" {
printf "%s", xmlbuf
xmlbuf=""
}
{ print }
Upvotes: 1
Views: 115
Reputation: 11207
Using sed
$ sed -z 's/.*/&&/;s/\(bean\)[[:alpha:]]/\1B/2;s/\(runas_\)[[:alpha:]]/\1b/2' input_file
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanB_users</role-name>
<principal-name>runas_b</principal-name>
</security-role-assignment>
Upvotes: 2
Reputation: 3975
# if your strings are static
# beanA_users#beanB_users
# runas_a#runas_b
# Try this
$ awk 'NR!=FNR{gsub(/beanA_users/,"beanB_users"); gsub(/runas_a/,"runas_b")}1' in.xml in.xml
<security-role-assignment>
<role-name>beanA_users</role-name>
<principal-name>runas_a</principal-name>
</security-role-assignment>
<security-role-assignment>
<role-name>beanB_users</role-name>
<principal-name>runas_b</principal-name>
</security-role-assignment>
Upvotes: 2