Rom*_*man 5 xml bash parsing sh
<root>
<tag>1</tag>
<tag1>2</tag1>
</root>
Run Code Online (Sandbox Code Playgroud)
需要从bash更改值1和2
Cha*_*ffy 12
要使用XMLStarlet将tag
值改为2
和tag1
值3
,请使用XMLStarlet:
xmlstarlet ed \
-u '/root/tag' -v 2 \
-u '/root/tag1' -v 3 \
<old.xml >new.xml
Run Code Online (Sandbox Code Playgroud)
使用您的示例输入:
xmlstarlet ed \
-u '/root/tag' -v 2 \
-u '/root/tag1' -v 3 \
<<<'<root><tag>1</tag><tag1>2</tag1></root>'
Run Code Online (Sandbox Code Playgroud)
...作为输出发出:
<?xml version="1.0"?>
<root>
<tag>2</tag>
<tag1>3</tag1>
</root>
Run Code Online (Sandbox Code Playgroud)
Mit*_*del 11
您可以使用以下XSLT表中的xsltproc
命令(来自xsltproc
基于Debian的发行版上的包):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="tagReplacement"/>
<xsl:param name="tag1Replacement"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tag">
<xsl:copy>
<xsl:value-of select="$tagReplacement"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tag1">
<xsl:copy>
<xsl:value-of select="$tag1Replacement"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
然后使用命令:
xsltproc --stringparam tagReplacement polop \
--stringparam tag1Replacement palap \
transform.xsl input.xml
Run Code Online (Sandbox Code Playgroud)
或者你也可以使用正则表达式,但通过正则表达式修改XML是纯粹的邪恶:)
我的$ 0.02 in python因为它会在你登录的每台服务器上
import sys, xml.etree.ElementTree as ET
data = ""
for line in sys.stdin:
data += line
tree = ET.fromstring(data)
nodeA = tree.find('.//tag')
nodeB = tree.find('.//tag1')
tmp = nodeA.text
nodeA.text = nodeB.text
nodeB.text = tmp
print ET.tostring(tree)
Run Code Online (Sandbox Code Playgroud)
这从stdin读取,所以你可以像这样使用它:
$ echo '<node><tag1>hi!</tag1><tag>this</tag></node>' | python xml_process.py
<node><tag1>this</tag1><tag>hi!</tag></node>
Run Code Online (Sandbox Code Playgroud)
编辑 - 接受挑战
这是一个有效的xmllib实现(应该回到python 1.6).我觉得用叉子刺我的眼睛会更有趣.我唯一想到的就是它适用于给定的用例.
import sys, xmllib
class Bag:
pass
class NodeSwapper(xmllib.XMLParser):
def __init__(self):
print 'making a NodeSwapper'
xmllib.XMLParser.__init__(self)
self.result = ''
self.data_tags = {}
self.current_tag = ''
self.finished = False
def handle_data(self, data):
print 'data: ' + data
self.data_tags[self.current_tag] = data
if self.finished:
return
if 'tag1' in self.data_tags.keys() and 'tag' in self.data_tags.keys():
b = Bag()
b.tag1 = self.data_tags['tag1']
b.tag = self.data_tags['tag']
b.t1_start_idx = self.rawdata.find(b.tag1)
b.t1_end_idx = len(b.tag1) + b.t1_start_idx
b.t_start_idx = self.rawdata.find(b.tag)
b.t_end_idx = len(b.tag) + b.t_start_idx
# swap
if b.t1_start_idx < b.t_start_idx:
self.result = self.rawdata[:b.t_start_idx] + b.tag + self.rawdata[b.t_end_idx:]
self.result = self.result[:b.t1_start_idx] + b.tag1 + self.result[b.t1_end_idx:]
else:
self.result = self.rawdata[:b.t1_start_idx] + b.tag1 + self.rawdata[t1_end_idx:]
self.result = self.result[:b.t_start_idx] + b.tag + self.rresult[t_end_idx:]
self.finished = True
def unknown_starttag(self, tag, attrs):
print 'starttag is: ' + tag
self.current_tag = tag
data = ""
for line in sys.stdin:
data += line
print 'data is: ' + data
parser = NodeSwapper()
parser.feed(data)
print parser.result
parser.close()
Run Code Online (Sandbox Code Playgroud)
既然您sed
在其中一条评论中举了一个例子,我想您想要一个纯 bash 解决方案?
while read input; do
for field in tag tag1; do
case $input in
*"<$field>"*"</$field>"* )
pre=${input#*"<$field>"}
suf=${input%"</$field>"*}
# Where are we supposed to be getting the replacement text from?
input="${input%$pre}SOMETHING${input#$suf}"
;;
esac
done
echo "$input"
done
Run Code Online (Sandbox Code Playgroud)
这是完全不智能的,显然只适用于具有同一行的开始标记和结束标记的格式良好的输入,同一行不能有多个相同标记的实例,要替换的标记列表是硬编码等
我无法想象这种情况会实际有用,并且比脚本或适当的 XML 方法更可取。