linux:sed修改xml中的值示例
2023-04-18 15:36:56 时间
如下是一个简单的xml配置文件, defaultConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<root description="root参数配置">
<password description="root帐户密码">root</password>
</root>
<server description="Thrift服务参数配置">
<start description="Thrift服务端是否启动">true</start>
<port description="服务端口号">28081</port>
<connectiontLimit description="最大连接数"></connectiontLimit>
<idleConnectionTimeout description="空闲连接超时[秒]"></idleConnectionTimeout>
<workerThreadCount description="工作线程数"></workerThreadCount>
</server>
<xhr description="XHR(XML HTTP Request)服务参数配置">
<start description="XHR服务端是否启动">true</start>
<port description="XHR服务端口">28082</port>
</xhr>
<restful description="RESTful web服务参数配置">
<start description="RESTful 服务端是否启动">true</start>
<port description="RESTful服务端口">8080</port>
<swaggerEnable description="是否显示在线swagger文档">true</swaggerEnable>
<corsEnable description="是否支持跨域访问(CORS)">true</corsEnable>
</restful>
</configuration>
上面的xml中有server.start
,xhr.start
,restful.start
.等三个前缀不同后缀相同的字段。
现在希望通过shell脚本修改server.start
字段为false
.
因为xml中有多个start
字段,所以肯定不能简单的使用sed全局替换来实现。
基本的思路就是要在指定范围内进行搜索替换。
首先确定搜索范围:
通过在xml中查找server
的起始标记<server>
和结束标记<server>
来确定搜索起始行号和结束行号
然后在搜索范围内进行正则表达式匹配替换
实现如下:
# 查找起始标志 <server 获取sed搜索范围的起始行号, = 用于打印行号
begin_line=$(sed -n '/<server/=' defaultConfig.xml )
# begin_line 为 6
# 查找结束标志</server>获取sed搜索范围的结束行号
end_line=$(sed -n '/</server>/=' defaultConfig.xml)
# end_line为 12
# 在line 6-12之间搜索招待正则表达式替换
sed -i -r "$begin_line,${end_line}s/(<start.*>).*(</start>)/1false2/1" defaultConfig.xml
封装为方便调用的函数
如果经常用到修改xml参数的情况,显然封装成一个方便调用的函数会更方便使用
如下实现了一个set_xml_value
shell函数用于修改xml文件属性值,
#!/bin/bash
# 查找xml文件中指定tag的起始和结束标志
# 执行成功 tag_begin 保存起始标志行号,tag_end 保存结束标志行号
# $1 xml file
# $2 tag name
# 正常执行返回0,
# $1 不存在,$2为空返回255
# 有多个相同节点,没找到节点则失败返回255
function find_xml_tags()
{
find_xml_tag_begin=
find_xml_tag_end=
if [ -f "$1" ] && [ -n "$2" ]
then
# 将.分割的节点名转为数组
local array=(${2//./ })
local size=${#array[@]}
#echo size=$size
if [ $size -ge 1 ]
then
local tag=${array[0]}
[ -z "$tag" ] && return 255
# 查找第一个节点
tag_begin=$(sed -n -r "/<s*$tag/=" "$1" ) &&
tag_end=$(sed -n -r "/</s*$tags*>/=" "$1" )
local ab=($tag_begin)
local ae=($tag_end)
# 找到标记数量不是1则失败返回
if [ ${#ab[@]} -ne 1 ] || [ ${#ae[@]} -ne 1 ] ; then return 255 ; fi
#echo $tag tag_begin=$tag_begin tag_end=$tag_end
# 根据第一个顶级节点给定的行号范围循环查找所有其他子节点
# 以后的每次循环都在上次找到的行号范围内查找,会一步步缩小范围
for (( i = 1 ; i < $size ; i++ ))
do
tag=${array[i]}
[ -z "$tag" ] && return 255
# 在$tag_begin,tag_end给定范围的值内查找
local b=$(sed -n "$tag_begin,${tag_end}p" "$1" | sed -n -r "/<s*$tag/=")
local e=$(sed -n "$tag_begin,${tag_end}p" "$1" | sed -n -r "/</s*$tags*>/=")
local ab=($b)
local ae=($e)
# 找到标记数量不是1则失败返回
if [ ${#ab[@]} -ne 1 ] || [ ${#ae[@]} -ne 1 ] ; then return 255 ; fi
#echo b=$b e=$e
# b,e都是相对位置,在这里要转换为整文件的行号
let "tag_end=$tag_begin+$e-1"
let "tag_begin=$tag_begin+$b-1"
#echo $tag tag_begin=$tag_begin tag_end=$tag_end
done
return 0
fi
fi
return 255
}
# 设置xml文件中指定property的值
# $1 xml file
# $2 .分割的节点的字符串,如 database.jdbc
# $3 value
# 正常执行返回0
# $1 不存在,$2为空返回255
# 有多个相同节点,没找到节点则失败返回255
# sed 修改文件失败返回sed错误代码
function set_xml_value()
{
find_xml_tags "$1" "$2" || exit
local last=${2##*.}
sed -i -r "$tag_begin,${tag_end}s!(<s*$last.*>).*(</s*$lasts*>)!1$32!1" "$1" || exit
}
调用示例
# 修改defaultConfig.xml中server.start的值为false
set_xml_value defaultConfig.xml server.start false
相关文章
- 【技术种草】cdn+轻量服务器+hugo=让博客“云原生”一下
- CLB运维&运营最佳实践 ---访问日志大洞察
- vnc方式登陆服务器
- 轻松学排序算法:眼睛直观感受几种常用排序算法
- 十二个经典的大数据项目
- 为什么使用 CDN 内容分发网络?
- 大数据——大数据默认端口号列表
- Weld 1.1.5.Final,JSR-299 的框架
- JavaFX 2012:彻底开源
- 提升as3程序性能的十大要点
- 通过凸面几何学进行独立于边际的在线多类学习
- 利用行动影响的规律性和部分已知的模型进行离线强化学习
- ModelLight:基于模型的交通信号控制的元强化学习
- 浅谈Visual Source Safe项目分支
- 基于先验知识的递归卡尔曼滤波的代理人联合状态和输入估计
- 结合网络结构和非线性恢复来提高声誉评估的性能
- 最佳实践丨云开发CloudBase多环境管理实践
- TimeVAE:用于生成多变量时间序列的变异自动编码器
- 具有线性阈值激活的神经网络:结构和算法
- 内网渗透之横向移动 -- 从域外向域内进行密码喷洒攻击