使用sed

时间:2015-09-29 21:27:09

标签: xml bash sed

我在Linux和我的XML文件中工作,当数字值增加1时,我想用另一个字符串替换<version>标记值。例如,如果我有这样的XML文件:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.rm.core</groupId>
    <artifactId>rm-dt-agr</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>rm-dt-agr</name>
</project>

我想将标记0.0.1-SNAPSHOT中的<version>替换为0.0.2-SNAPSHOT 如果是0.0.2-SNAPSHOT值,我想将其替换为0.0.3-SNAPSHOT 等等...

我尝试使用“sed”命令但没有成功。

1 个答案:

答案 0 :(得分:0)

在这种情况下,你应该真正使用一种用于处理XML的工具而不是试图窃取bash解决方案。话虽如此,对于涉及最小格式体操的简单标签替换,bash可以很好地工作。

对于您要更改文件中某一行的任何情况,您需要将更改写入新文件或临时文件,然后复制以替换原始文件。 (虽然从理论上讲,既然你只是改变一个字符而不是调整行长,你真的可以把改变写入新文件,但要注意)

这里的难点是你有一个 5个字符的刺痛,其中 3个数字用 '.'(句点)分隔,而不是一个简单的数字。无论你选择什么工具,你都会进行一些字符串操作来解析你知道需要增加的值的点。然后,一旦找到,您必须保留格式(这意味着您必须考虑增量导致您的值从一位数号码更改为两位数号码的任何时间)据推测,如果增量导致单个数字溢出,则必须调整下一个数字的值。

您可以采取几种方法。您可以手动创建反映更改的新文件,方法是将所有行(除了更改的行)写入新文件而不进行任何修改。当然,也可以写下更改的行。第二种方法是解析文件以获取需要更改的行,进行计算以增加数字,然后使用sed进行替换。

以下采用手动方法并编写完整的新文件。仔细看看,试一试,记住 - 你最好找一个解析和修改XML的XML工具...

#!/bin/bash

[ -z $1 ] && {  ## validate input file given
    printf "error: insufficient input. usage: %s filename\n" "${0//*\//}"
    exit 1
}

[ -r $1 ] || {  ## validate input file readable
    printf "error: file not found/readable\n" "$1"
    exit 1
}

ifile="$1"      ## set input/output filename, truncate output file
ofile="${2:-newxml.xml}"
:> "$ofile"

while IFS= read -r line; do                     ## for each line
    text="${line// /}"                          ## remove leading spaces
    if [ "${text//>*/}" = '<version' ]; then    ## match version tag 
        nspcs=$((${#line} - ${#text}))          ## save # spaces removed
        value="${text#<version>}"               ## strip tags from ends
        value="${value%</version>}"
        nstr="${value%-*}"                      ## separate number string
        label="${value#*-}"                     ## from text -SNAPSHOT
        IFS=. read v1 v2 v3 <<<"$nstr"          ## read separate numbers
        [ -z $v1 -o -z $v2 -o -z $v3 ] && {     ## validate
            printf "error invalid value: '%s'\n" "$value"
            continue
        }
        v3=$((v3 + 1))          ## increment by 1
        [ $v3 -eq 10 ] && {     ## adjust remaining if 10
            v3=0
            v2=$((v2 + 1))
        }
        [ $v2 -eq 10 ] && {
            v2=0
            v1=$((v1 + 1))
        }                       ## output updated line to new file
        printf "%*s%s\n" $nspcs " " "<version>$v1.$v2.$v3-$label</version>" >> "$ofile"
    else
        printf "%s\n" "$line" >> "$ofile"   ## write other lines unchanged
    fi
done <"$ifile"

exit 0

输入文件

$ cat dat/file.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.rm.core</groupId>
    <artifactId>rm-dt-agr</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>rm-dt-agr</name>
</project>

使用示例

$ bash xmlchgvalue.sh dat/file.xml dat/new.xml

输出文件

$ cat dat/new.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.rm.core</groupId>
    <artifactId>rm-dt-agr</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>rm-dt-agr</name>
</project>

<强>验证

$ diff dat/file.xml dat/new.xml
8c8
<     <version>0.0.1-SNAPSHOT</version>
---
>     <version>0.0.2-SNAPSHOT</version>