之前我发布了一个关于如何从命令行更改Maven项目版本的问题,这导致我遇到了一个新问题。

以前我能够获得版本号,因为版本存储为一个属性,很容易从命令行(bash)进行grep和解析。现在pom.xml <version>元素用于此,它不再是唯一的,因为所有依赖项(也许其他一些依赖项也使用它)。我认为,如果没有用于解析XML的外部工具或一些非常能感知上下文的sed命令,就无法用bash脚本获得当前版本号。

在我看来,最干净的解决方案是Maven发布这个版本信息。我想写一个自定义的maven插件检索不同的属性,但我想我应该先问这里。

那么,是否有任何简单的方法来获取${project的值。版本}到命令行?

解决方案

我必须手动cd到该目录,但这可以很容易地做到。在我的bash脚本我有:

version=`cd $project_loc && mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'`

这就得到了我可以改进的当前版本。Grepping可能更简单,但我认为我想尽可能健壮,所以我对以数字开头的第一行感到满意,并尝试将其作为版本号处理。

# Advances the last number of the given version string by one.
function advance_version () {
    local v=$1
    # Get the last number. First remove any suffixes (such as '-SNAPSHOT').
    local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'`
    local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'`
    local next_num=$(($last_num+1))
    # Finally replace the last number in version string with the new one.
    echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/"
}

我通过调用:

new_version=$(advance_version $version)

当前回答

如果您不介意将版本写入临时文件,那么还有另一种解决方案(不含grep/sed)适合我。(编辑:请参阅rjrjr的回答,这是一个更简单的解决方案,没有任何临时文件的麻烦)

我使用Exec Maven插件和echo二进制文件。与Maven Help Plugin相反,Exec Plugin允许输出重定向到文件,可以用来绕过grep/sed,甚至可以解析奇怪的东西,比如多行版本字符串(版本标记中带有CDATA块),至少在一定程度上是这样。

#!/usr/bin/env sh

MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT

mvn -Dexec.executable="echo" \
    -Dexec.args='${project.version}' \
    -Dexec.outputFile="$VERSION_FILE" \
    --non-recursive \
    --batch-mode \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
    { echo "Maven invocation failed!" 1>&2; exit 1; }

# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"

# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )

printf "Maven project version: %s\n" "$MVN_VERSION"

其他回答

如果您不介意将版本写入临时文件,那么还有另一种解决方案(不含grep/sed)适合我。(编辑:请参阅rjrjr的回答,这是一个更简单的解决方案,没有任何临时文件的麻烦)

我使用Exec Maven插件和echo二进制文件。与Maven Help Plugin相反,Exec Plugin允许输出重定向到文件,可以用来绕过grep/sed,甚至可以解析奇怪的东西,比如多行版本字符串(版本标记中带有CDATA块),至少在一定程度上是这样。

#!/usr/bin/env sh

MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT

mvn -Dexec.executable="echo" \
    -Dexec.args='${project.version}' \
    -Dexec.outputFile="$VERSION_FILE" \
    --non-recursive \
    --batch-mode \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
    { echo "Maven invocation failed!" 1>&2; exit 1; }

# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"

# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )

printf "Maven project version: %s\n" "$MVN_VERSION"

这是迄今为止最简单的bash剪切和粘贴解决方案:

VERSION=$(mvn exec:exec -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive -q)
echo $VERSION

它的回声

1.4

Maven帮助插件已经为此提出了一些建议:

help:evaluate以交互模式计算用户给出的Maven表达式。

下面是你如何在命令行上调用它来获得${project.version}:

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
    -Dexpression=project.version

正如Seb T的注释中所指出的,要只打印没有maven INFO日志的版本,另外使用-q -DforceStdout:

mvn help:evaluate -Dexpression=project.version -q -DforceStdout

在只有busybox可用的docker容器中,我使用awk。

version=$(
 awk '
  /<dependenc/{exit}
  /<parent>/{parent++};
  /<version>/{
    if (parent == 1) {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      parent_version = $0;
    } else {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      version = $0;
      exit
    }
  }
  /<\/parent>/{parent--};
  END {
    print (version == "") ? parent_version : version
  }' pom.xml
)

注:

如果没有给定工件版本,则打印父版本。 工件和父版本之后需要依赖关系。(这很容易克服,但我不需要它。)

我找到了适合自己的平衡。在mvn包后,maven-archiver插件创建了target/maven-archiver/pom。属性具有如下内容

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

我使用bash来执行它

. ./target/maven-archiver/pom.properties

then

echo $version
0.0.1-SNAPSHOT

当然,执行这个文件一点也不安全,但是可以很容易地将执行转换为perl或bash脚本,以便从该文件读取和设置环境变量。