给出一个包含一系列重复文本部分的文本文件,我应该如何提取这些部分并将其存储在名称来源于每个部分ID的单独文本文件中?
<?xml
开头,并以</svg>
结尾。我不确定要在for loop
中将两个sed REGEX组合在一起才能实现这一目标。
Original.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>
结果:
France.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>
Italy.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>
Ireland.svg:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>
答案 0 :(得分:1)
使用bash和xmlstarlet:
#!/bin/bash
while read -r line; do
# fill variable with all lines and append newline to every line
svg="$svg$line"$'\n'
# last line?
if [[ $line =~ \</svg\> ]]; then
# extract attribute from xml
svgfile=$(xmlstarlet select -N x='http://www.w3.org/2000/svg' --template --value-of '//x:svg/@id' <<< "$svg")
# remove trailing newline and output xml to new file
echo -e "${svg:0:-1}" > "${svgfile}.svg"
unset svg
fi
done < Original.svg
答案 1 :(得分:1)
使用用于多字符RS的GNU awk将每个SVG部分的文件分成有效的XML,进行协同处理以使我们将记录打印到xmlstarlet并读取输出,将第二个arg传递给close()
以使我们关闭到xmlstarlet的管道,以便它处理输入,而xmlstarlet实际读取XML:
$ cat ../tst.awk
BEGIN {
RS = "</svg>[[:space:]]*"
ORS = ""
xmlParser = "xmlstarlet select -N x=\047http://www.w3.org/2000/svg\047 --template --value-of \047//x:svg/@id\047"
}
RT != "" {
$0 = $0 RT
print |& xmlParser
close(xmlParser,"to")
if ( (xmlParser |& getline id) > 0 ) {
print > (id ".svg")
}
close(xmlParser)
}
例如,其中file
包含问题的输入文本:
$ ls
file tst.awk
$ awk -f tst.awk file
$ ls
file tst.awk France.svg Ireland.svg Italy.svg
$ tail -n +1 *.svg
==> France.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="France" width="1500" height="1000" viewBox="0 0 3 2">
<rect width="3" height="2" fill="#009246"/>
<rect width="2" height="2" x="1" fill="#fff"/>
<rect width="1" height="2" x="2" fill="#ce2b37"/>
</svg>
==> Ireland.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Ireland" width="1200" height="600">
<rect fill="#169b62" width="1200" height="600" />
<rect fill="#fff" x="400" width="800" height="600" />
<rect fill="#ff883e" x="800" width="400" height="600" />
</svg>
==> Italy.svg <==
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="Italy" width="900" height="600">
<rect width="900" height="600" fill="#ED2939"/>
<rect width="600" height="600" fill="#fff"/>
<rect width="300" height="600" fill="#002395"/>
</svg>
如果</svg>
位于注释或字符串中,并且可能还有其他您似乎没有的上下文,则失败。 idk如果XML部分中没有id
,您要怎么做,所以如果发生这种情况,我只是不打印XML。
答案 2 :(得分:-1)
这是一种易碎但可移植的awk解决方案。
awk '
{a[i++]=$0}
/^<svg/ {for(f=1; f<=NF; f++) if($f~/^id=/) split($f, id, /["=]+/)}
/^<\/svg/ {for(n=0; n<i; n++) print a[n] > (id[2] ".svg"); i=0}
' Original.svg
<svg
开头的行上,使用一个或多个等号或双引号将第三个字段分成数组id
。</svg
开头的行上,遍历数组,将每个元素(行)打印到文件中,方法是将拆分后的id[2]
的第二个结果与文件扩展名“ .svg”连接在一起。 如果您有帮助,请考虑投票并选择此答案。我会回答任何问题。
答案 3 :(得分:-1)
这是一个简化的awk脚本,用于查询您的请求。 假设文件结构一致,为6行。
{++line; lines = lines"\n"$0;}
NR%6 == 2 {id = substr($3, 5, length($3)-5)".svg"; next;}
NR%6 == 0 {
print lines > id;
line = 0; lines = "";
}
awk -f script.awk Original.svg
如果您需要注释中的解释要求。