【问题标题】:How can I cut the version number out of a pom file in bash如何从 bash 中的 pom 文件中删除版本号
【发布时间】:2015-06-07 20:05:09
【问题描述】:

我有一个包含以下信息的 pom 文件:

<modelVersion>4.0.0</modelVersion>
  <groupId>com.site.camera</groupId>
  <artifactId>proj3</artifactId>
  <packaging>pom</packaging>
  <version>2.6</version>
  <name>Proj 3</name>

我正在编写一个 bash 脚本并希望能够打开这个文件 (pom.xml) 并删除版本(例如,在这种情况下为 2.6)。我这样做是因为当我更新版本时,我希望脚本的其余部分也随之更新。

我尝试过的事情:

var=$(grep <version>2.6</version> pom.xml)
echo $var

请注意,我在 pom 文件中有多个版本参数。我需要这个被这个名称、包装、artifactId 等包围的特定版本。

【问题讨论】:

标签: xml bash maven sed grep


【解决方案1】:

that other guy 中的The answer 说明了使用 xml 解析器的正确方法,但它无法处理 pom.xml 文件中的命名空间。

如果你的 POM 文件是这样开始的:

<?xml version="1.0" encoding="UTF-8" ?>
<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"
>
 ...
</project>

使用xmlstarlet时需要添加命名空间:

xmlstarlet select \
  -N x="http://maven.apache.org/POM/4.0.0" \
  --template --value-of "/x:project/x:version" \
  pom.xml

【讨论】:

    【解决方案2】:

    我的要求也类似。我们在版本末尾使用 SNAPSHOT,所以我这样做是为了找出版本号(大卫答案的扩展)

    for i in $(grep '<version>' pom.xml); do
        #echo "$i"; 
        ver=${i%<*}; 
        ver=${ver#*>};
        if [[ $ver == *"SNAPSHOT"* ]]
            then
                echo "$ver";
        fi 
    
    done
    

    它给了我一个输出;我想要的

    1.09-快照

    【讨论】:

      【解决方案3】:

      或者不使用perl兼容的正则表达式使用参数扩展/子字符串提取

      $ var=$(grep '<version>' pom.xml); ver=${var%<*}; ver=${ver#*>}; echo $ver
      2.6
      

      如果你有可用的 perl 兼容 RE,我会更喜欢它。

      注意: 正如 David W. 所指出的,这适用于给定的示例,但如果输入文件超过一行,则会返回 multiple version 字符串包含&lt;version&gt;。下面在 cmets 中引用的完整 pom.xml 文件包含 多个 &lt;version&gt; 字符串。需要一个额外的循环来处理所有version 行,并且如果没有唯一标记,则无法确定哪个version 是所需的版本。例如解析当前完整的pom.xml

      $ for i in $(grep '<version>' pom.xml); do ver=${i%<*}; ver=${ver#*>}; echo "version: $ver"; done
      

      返回:

      version: 33
      version: 3.3.2
      version: 4.11
      version: 2.4
      version: 3.2
      version: 2.9.1
      version: 2.5.2
      version: 2.5.1
      version: 2.4
      version: 3.0.1
      version: 2.4
      version: 2.0
      version: 1.7
      

      【讨论】:

      • 查看pom.xmlcommons-lang3。您的grep 将获取近十几个&lt;version&gt; 元素。
      • 嗯,这确实改变了一些事情!我只是按照给出的例子。感谢您的提醒。我会看看它是否可以挽救,如果没有,我会记下它。
      【解决方案4】:

      最简单的方法是使用 GNU grep 的 perl 兼容正则表达式

      grep -oP '<version>\K[^<]+' pom.xml
      

      使用 sed,你会写

      sed -n 's/^[[:blank:]]*<version>\([^<]\+\).*/\1/p' pom.xml
      

      感谢 David W. 的深思熟虑的评论:解决方案必须使用 XML 解析器。 xmlstarlet 就是这样一种工具:

      ver=$( xmlstarlet sel -t -v /project/version pom.xml )
      

      为了与众不同,ruby 在其标准库中附带了一个 XML 解析器:

      ruby -r rexml/document -e 'puts REXML::Document.new(File.new(ARGV.shift)).elements["/project/version"].text' pom.xml
      

      【讨论】:

      • 如果pom中还有其他带有版本号的行怎么办?每个依赖项和插件都有一个版本号。
      • &lt;version/&gt; 属性在整个pom.xml 中都可以找到。看看这个commons-lang3。有一个父 &lt;version&gt;,一个工件 &lt;version&gt;,以及三个带有 &lt;version&gt; 的依赖项。 &lt;reporting&gt; 部分有 5 个,&lt;build&gt; 部分有 2 个。这个 grep 将把它们全部捡起来。
      • xmlstarlet 行对我不起作用,但效果很好 -> version=$( xmlstarlet sel -t -v '/_:project/_:version' pom.xml )跨度>
      【解决方案5】:

      有些人object to parsing XML with regex。以下是使用xmlstarlet 正确且稳健地执行此操作的方法:

      $ cat pom.xml 
      <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.site.camera</groupId>
        <artifactId>proj3</artifactId>
        <packaging>pom</packaging>
        <version>2.6</version>
        <name>Proj 3</name>
      </project>
      
      $ xmlstarlet sel -t -v '/project/version' pom.xml 
      2.6
      

      在 XML 工具和编辑器对您的文档进行处理后,这同样适用:

      $ cat pom.xml 
      <project>
        <version><![CDATA[2]]>&#x002E;6
        </version>
      </project>
      
      $ xmlstarlet sel -t -v '/project/version' pom.xml 
      2.6
      

      编辑:作为Doing It Right(tm)的证明,这个解决方案在被指出会有很多不同的版本标签之后仍然可以正常工作。

      【讨论】:

      • 其他人可能反对使用 DOM 解析 maven 配置 :) +1。但我有另一个解决方案。
      • 当pom文件以&lt;project xmlns=...&gt;开头时,select语句也需要定义命名空间。我添加了一个 answer 来说明这一点。
      【解决方案6】:

      使用 maven 你可以这样做:

      echo '${project.version}' | mvn help:evaluate | grep -v '^[[]'
      

      【讨论】:

      • 非常好。遗憾的是,-q-l /dev/null2&gt; /dev/null 都不会说服 mvn 将输出与构建日志分开,因此 grep 似乎是唯一的方法。
      【解决方案7】:

      试试这样:

      var=$(grep -Po '<version>\K[^<]*' pom.xml)
      echo $var
      

      输出:

      2.6
      
      • -P : 使用 perl 正则表达式格式
      • -o : 仅打印匹配部分

      【讨论】:

        猜你喜欢
        • 2014-06-23
        • 1970-01-01
        • 1970-01-01
        • 2014-10-22
        • 2021-05-01
        • 2023-04-08
        • 2011-01-14
        • 2018-01-16
        • 1970-01-01
        相关资源
        最近更新 更多