解析并替换两个文件中的一些字符串

时间:2011-11-05 16:39:30

标签: linux parsing sed substitution

我想运行这个用法的shell脚本:

./run A.txt B.xml

A.txt包含一些统计信息:

Accesses = 1
Hits = 2
Misses = 3
Evictions = 4
Retries = 5

B.xml看起来像:

<stat name="total_accesses" value="0"/>
<stat name="total_misses" value="0"/>
<stat name="conflicts" value="0"/>  

我想从A.txt替换B.xml中的一些统计信息。例如,我想

1- find "Accesses" in A.txt
2- find "total_accesses" in B.xml
3- replace 0 with 1
1- find "Misses" in A.txt
2- find "total_misses" in B.xml
3- replace 0 with 3

所以B.xml看起来像是:

<stat name="total_accesses" value="1"/>
<stat name="total_misses" value="3"/>
<stat name="conflicts" value="0"/>  

我想用shell“sed”命令做到这一点。但是我发现它很复杂,因为正则表达式很难理解。

“sed”能帮助我解决这个问题,还是我必须找到另一种方法?

3 个答案:

答案 0 :(得分:1)

这是一个执行您想要的shell脚本:


#!/bin/bash
while read line
do
    key=`echo $line | cut -d' ' -f1`
    value=`echo $line | cut -d' ' -f3`
    xmlLine=`grep -i $key $2`
    if [ -n "$xmlLine" ]; then
        for num in `seq 5`
        do
            field[${num}]=`echo "$xmlLine" | cut -d'"' -f${num}`
        done
        echo ${field[1]}\"${field[2]}\"${field[3]}\"$value\"${field[5]}
    fi
done 

You can copy it to a file say A.sh , give run permissions to it (chmod +x A.sh) and then:

A.sh

请注意,此代码不适合生产,正则表达式对这些脚本至关重要。

答案 1 :(得分:1)

虽然你可以在命令行上破解它,但我建议你不要这样做。

XML太脆弱而无法以这种方式处理 - 使用适当的XML库并在操作之前解析XML。否则你很容易就会破坏XML。例如用Ruby,Python或Perl编写脚本并使用XML库。

答案 2 :(得分:1)

对于这样一个简单的案例,这可能有点重,但这里有一个Python脚本可以完成这项工作:

#!/usr/bin/env python
import sys
import xml.etree.ElementTree as etree

# read A.txt; fill stats
stats = {}
for line in open(sys.argv[1]):
    if line.strip():
        name, _, count = line.partition('=')
        stats["total_"+name.lower().strip()] = count.strip()

# read B.xml; fix to make it a valid xml; replace stat[@value]
root = etree.fromstring("<root>%s</root>" % open(sys.argv[2]).read())
for s in root:
    if s.get('name') in stats:
        s.set('value', stats[s.get('name')])
    print etree.tostring(s),

实施例

$ python fill-xml-template.py A.txt B.xml 
<stat name="total_accesses" value="1" />
<stat name="total_misses" value="3" />
<stat name="conflicts" value="0" /> 

要逐步处理输入文件或进行更改,您可以使用以下内容:

#!/usr/bin/env python
import fileinput
import sys
import xml.etree.ElementTree as etree

try: sys.argv.remove('-i')
except ValueError: 
    inplace = False
else: inplace = True # make changes inplace if `-i` option is specified

# read A.txt; fill stats
stats = {}
for line in open(sys.argv.pop(1)):
    if line.strip():
        name, _, count = line.partition('=')
        stats["total_"+name.lower().strip()] = count.strip()

# read input; replace stat[@value]
for line in fileinput.input(inplace=inplace):
    s = etree.fromstring(line)
    if s.get('name') in stats:
        s.set('value', stats[s.get('name')])
    print etree.tostring(s)

实施例

$ python fill-xml-template.py A.txt B.xml -i

它可以从stdin读取或处理多个文件:

$ cat B.xml | python fill-xml-template.py A.txt
<stat name="total_accesses" value="1" />
<stat name="total_misses" value="3" />
<stat name="conflicts" value="0" />