0

我希望为比通常通过 sed 查找/替换稍微复杂的东西编写一个 bash 脚本。我有一本名为 bash Cookbook 的书,我一直试图从中获得一些灵感,但我并没有走得太远。

基本上我正在尝试编写一个脚本来自动更新一堆 maven pom.xml 文件中的版本号。这是我正在查看的一般设置:

<!-- TEMPLATE:BEGIN
    <version>@@VERSION@@</version>
-->
    <version>1.0.0</version>
<!-- TEMPLATE:END -->

运行脚本(使用新版本号 1.0.1)后,我希望文件改为读取:

<!-- TEMPLATE:BEGIN
    <version>@@VERSION@@</version>
-->
    <version>1.0.1</version>
<!-- TEMPLATE:END -->

所以这将在实际发布的 pom 文件中,1.0.0 是当前版本(我试图用 1.0.1 或其他东西替换它)。显然版本号会发生变化,所以没有一个很好的方法来查找/替换(因为你想要找到的东西是可变的)。我希望能够编写一个 bash 脚本

  1. 将@@VERSION@@ 替换为实际的版本号
  2. 删除当前版本行
  3. 在 TEMPLATE:END 之前的行上写入更新的版本行(同时在文件中保留 @@VERSION@@ - 可能通过将模板写入临时文件,进行替换,然后返回来做到这一点?)

我可以使用 ant 脚本 a la 做一些这样的事情(写出一个新文件,做替换)
<replace file="pom.xml">
<replacefilter token="@@VERSION@@" value="${version}"/>
</replace>

但我不确定a.)删除旧版本的行或b.)告诉它在正确的位置复制新行的最佳方法是什么。任何人都知道如何做到这一点或有任何建议?

4

3 回答 3

3

假设新版本号在 shell 变量$VERSION中,那么您应该能够使用:

sed -e '/<!-- TEMPLATE:BEGIN/,/<!-- TEMPLATE:END -->/{
        s/<version>[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*<\/version>/<version>'$VERSION'<\/version>/
        }'

请注意,这将忽略带有 的模板版本行@@VERSION@@,但仅匹配出现在包含 TEMPLATE:BEGIN 和 TEMPLATE:END 的行之间的由三部分组成的版本号,而将其他所有内容(包括包含<version>...</version>元素的其他行)单独保留。

您可以决定如何进行文件覆盖(也许您的版本sed来自 GNU,它会根据请求自动执行该-i选项)等。您还可以使用更强大的正则表达式符号来实现更紧凑的匹配。但是,这应该适用于大多数版本而sed无需更改。

于 2012-05-25T21:44:25.007 回答
1

您概述的步骤(1-3)看起来好像您实际上并不关心根据注释中定义的模板化规则执行替换。

因此,这里有一些代码,其行为与您概述的一样:

#!/bin/bash

file=$1
newversion=$2

sed -i $file -e "s|<version>\([^@]*\)</version>|<version>$newversion</version>|"

运行:

chmod +x yourscript.sh
./yourscript.sh filetoupdate.xml 1.0.1
于 2012-05-25T21:44:48.110 回答
0
use 5.010;
use strictures;
use Perl::Version qw();
use XML::LibXML qw();

my $dom = XML::LibXML->load_xml(location => 'pox.xml');

for my $node ($dom->findnodes('//version')) {
    my $version = Perl::Version->new($node->textContent);
    $version->inc_subversion;
    $version->stringify;
    $node->removeChildNodes;
    $node->appendText($version);
};

say $dom->toString;
于 2012-05-25T21:53:23.853 回答