Regex 更新pom文件中标记之间文本的Bash脚本?

Regex 更新pom文件中标记之间文本的Bash脚本?,regex,sed,pom.xml,Regex,Sed,Pom.xml,我用谷歌搜索了一下,但找不到具体的答案。 我有一个带有以下标记的pom.xml文件 <properties> <rpm.release>10</rpm.release> </properties> 10 然后我有一个脚本,它在标签之间寻找标签,这很有效 update_rpm_release_in_pom() { BUILD_NUM=$1 POM_FILE="./template/iptools/pom.xml" BEGIN

我用谷歌搜索了一下,但找不到具体的答案。

我有一个带有以下标记的pom.xml文件

<properties>
    <rpm.release>10</rpm.release>
</properties>

10
然后我有一个脚本,它在标签之间寻找标签,这很有效

update_rpm_release_in_pom()
{
  BUILD_NUM=$1
  POM_FILE="./template/iptools/pom.xml"
  BEGIN_PROPERTIES="n"
  # Look for the <rpm.release> tag in the <properties>
  # and update with with passed-in build_num
  cat $POM_FILE | while read LINE
  do
    case $BEGIN_PROPERTIES in
      n) # <property> tag not found yet
        if [[ "$LINE" == *\<properties\>* ]]; then
          BEGIN_PROPERTIES="y"
        fi
        continue
      ;;
      y) # <property> tag found
        if [[ "$LINE" == *\</properties\>* ]]; then
          # </property> tag found, stop searching
          break
        fi
        if [[ "$LINE" == *rpm.release* ]]; then
          # Update value
          ####################################
          # How do I update value??????
          ####################################
          break
        fi
      ;;
    esac
  done
}

# Call above function    
update_rpm_release_in_pom 11
更新\u pom()中的\u rpm\u release\u
{
BUILD_NUM=$1
POM_FILE=“./template/iptools/POM.xml”
BEGIN_PROPERTIES=“n”
#在地图上寻找标签
#并使用传入的build_num进行更新
cat$POM_文件|在读取行时
做
案例$BEGIN\u中的属性
n) #尚未找到标签
如果[[“$LINE”==*\*];则
开始_PROPERTIES=“y”
fi
持续
;;
y) #找到标签
如果[[“$LINE”==*\*];则
#已找到标记,请停止搜索
打破
fi
如果[[“$LINE”==*rpm.release*];则
#更新值
####################################
#如何更新值??????
####################################
打破
fi
;;
以撒
完成
}
#调用上述函数
更新pom 11中的rpm版本
我应该在“#如何更新值??”中输入什么?因此,当我运行脚本时,pom.xml现在已经

<properties>
    <rpm.release>11</rpm.release>
</properties>

11
谢谢。

你可以用

[[ $LINE =~ ^([^>]+>)([0-9]+)(.*) ]] && printf -v LINE "%s%d%s" \
    "${BASH_REMATCH[1]}" \
    $(( ${BASH_REMATCH[2]} + 1 )) \
    "${BASH_REMATCH[3]}"
是由
=~
运算符设置的数组,用于将值存储在括号内


它只是更新了线路。我会使用我最喜欢的命令行xml工具完全重写它:

update_rpm_release_in_pom() {
    local f=pom.xml
    # get the current value
    local current=$(xmlstarlet sel -t -v '/properties/rpm.release' $f)
    local new=$(( current + 1 ))
    # update the xml with the new value and save it
    xmlstarlet ed -u '/properties/rpm.release' -v $new $f > $f.$new &&
      mv $f $f.$current &&
      mv $f.$new $f
}
你可以用

[[ $LINE =~ ^([^>]+>)([0-9]+)(.*) ]] && printf -v LINE "%s%d%s" \
    "${BASH_REMATCH[1]}" \
    $(( ${BASH_REMATCH[2]} + 1 )) \
    "${BASH_REMATCH[3]}"
是由
=~
运算符设置的数组,用于将值存储在括号内


它只是更新了线路。我会使用我最喜欢的命令行xml工具完全重写它:

update_rpm_release_in_pom() {
    local f=pom.xml
    # get the current value
    local current=$(xmlstarlet sel -t -v '/properties/rpm.release' $f)
    local new=$(( current + 1 ))
    # update the xml with the new value and save it
    xmlstarlet ed -u '/properties/rpm.release' -v $new $f > $f.$new &&
      mv $f $f.$current &&
      mv $f.$new $f
}

由于问题被标记,我认为
awk
将是一个有效的选择

在这种情况下,您可以在
awk
中处理pom文件,将结果保存在tmpfile中,并用修改后的版本覆盖原始文件:

#!/bin/sh

# error function
error(){
 echo -e >&2 "error: $@"
 exit 1
}

update_rpm_release_in_pom()
{
  #################
  # set constants #
  #################

  POM_FILE="./template/iptools/pom.xml"
  USAGE="usage: update_rpm_release_in_pom <build num>"

  #################
  # sanity checks #
  #################

  # argument given?
  [[ $# -eq 1 ]] || \
    error "wrong number of parameters\n$USAGE"

  # pom file exists?
  [[ -e "$POM_FILE" ]] || \
    error "pom file $POM_FILE does not exist"

  # pom file readable?
  [[ -r "$POM_FILE" ]] || \
    error "pom file $POM_FILE is not readable"

  # pom file writeable?
  [[ -w "$POM_FILE" ]] || \
    error "pom file $POM_FILE is not writeable"

  ##################
  # set parameters #
  ##################

  BUILD_NUM=$1

  ###############################
  # create temporal output file #
  # and ensure its removal      #
  ###############################

  # cleanup function
  cleanup(){
    [[ -e "$TMP_FILE" ]] && rm -- "$TMP_FILE"
  }

  # ensure cleanup on exit
  trap 'cleanup' EXIT

  # create temporal output file or exit with error
  TMP_FILE=`mktemp` || \
    error "could not create temporal output file"

  #############################
  # process pom file with awk #
  # and save modified version #
  # in temporal output file   #
  #############################

  awk \
    -F "rpm.release>" \
    -v OFS="rpm.release>" \
    -v BUILD_NUM="$BUILD_NUM" \
    '
      /<properties>/{
        properties=1
      }
      /<\/properties>/{
        properties=0
      }
      properties&&$1~/<$/&&$2~/<\/$/{
        $2=BUILD_NUM"</"
      }
      1
    ' "$POM_FILE" > "$TMP_FILE" || \
    error "processing pom file $POM_FILE with awk failed"

  #########################
  # move modified version #
  # back to original path #
  #########################

  mv -- "$TMP_FILE" "$POM_FILE" || \
    error "could not mv temporal output file $TMP_FILE to pom file $POM_FILE"
}

# Call above function
update_rpm_release_in_pom 11
然而,这并不像上述解决方案那样稳定。 例如,在我的机器上,这会从pom文件中删除前导空格。 我不知道这是由于报价问题还是您需要调整
read
echo
的参数。
因为我永远不会使用这样的解决方案,所以我不会对此进行进一步调查,但如果您坚持使用
bash
-唯一的解决方案,这可能会对您有所帮助。

由于问题被标记,我想
awk
将是一个有效的替代方案

在这种情况下,您可以在
awk
中处理pom文件,将结果保存在tmpfile中,并用修改后的版本覆盖原始文件:

#!/bin/sh

# error function
error(){
 echo -e >&2 "error: $@"
 exit 1
}

update_rpm_release_in_pom()
{
  #################
  # set constants #
  #################

  POM_FILE="./template/iptools/pom.xml"
  USAGE="usage: update_rpm_release_in_pom <build num>"

  #################
  # sanity checks #
  #################

  # argument given?
  [[ $# -eq 1 ]] || \
    error "wrong number of parameters\n$USAGE"

  # pom file exists?
  [[ -e "$POM_FILE" ]] || \
    error "pom file $POM_FILE does not exist"

  # pom file readable?
  [[ -r "$POM_FILE" ]] || \
    error "pom file $POM_FILE is not readable"

  # pom file writeable?
  [[ -w "$POM_FILE" ]] || \
    error "pom file $POM_FILE is not writeable"

  ##################
  # set parameters #
  ##################

  BUILD_NUM=$1

  ###############################
  # create temporal output file #
  # and ensure its removal      #
  ###############################

  # cleanup function
  cleanup(){
    [[ -e "$TMP_FILE" ]] && rm -- "$TMP_FILE"
  }

  # ensure cleanup on exit
  trap 'cleanup' EXIT

  # create temporal output file or exit with error
  TMP_FILE=`mktemp` || \
    error "could not create temporal output file"

  #############################
  # process pom file with awk #
  # and save modified version #
  # in temporal output file   #
  #############################

  awk \
    -F "rpm.release>" \
    -v OFS="rpm.release>" \
    -v BUILD_NUM="$BUILD_NUM" \
    '
      /<properties>/{
        properties=1
      }
      /<\/properties>/{
        properties=0
      }
      properties&&$1~/<$/&&$2~/<\/$/{
        $2=BUILD_NUM"</"
      }
      1
    ' "$POM_FILE" > "$TMP_FILE" || \
    error "processing pom file $POM_FILE with awk failed"

  #########################
  # move modified version #
  # back to original path #
  #########################

  mv -- "$TMP_FILE" "$POM_FILE" || \
    error "could not mv temporal output file $TMP_FILE to pom file $POM_FILE"
}

# Call above function
update_rpm_release_in_pom 11
然而,这并不像上述解决方案那样稳定。 例如,在我的机器上,这会从pom文件中删除前导空格。 我不知道这是由于报价问题还是您需要调整
read
echo
的参数。

因为我永远不会使用这样的解决方案,所以我不会对此进行进一步的研究,但如果您坚持使用
bash
-唯一的解决方案,这可能会对您有所帮助。

我想,按照关于regex和XML的常见警告,您可以使用regex来实现这一点。很容易。谢谢,我知道这些警告,但我相信我的情况很简单,我可以接受它们。我不是正则表达式专家。您需要增加版本号还是只将其设置为硬编码值?我需要将其设置为存储在局部变量$BUILD_NUM中的传入值。
perl-pi-e's/10/11/g'
,而不是bash,但应该这样做。我想,按照关于正则表达式和XML的常见警告,您可以使用正则表达式来实现这一点。很容易。谢谢,我知道这些警告,但我相信我的情况很简单,我可以接受它们。我不是正则表达式专家。您需要增加版本号还是只将其设置为硬编码值?我需要将其设置为存储在局部变量$BUILD_NUM中的传入值。
perl-pi-e's/10/11/g'
,而不是bash,但应该这样做。那么这如何适合我的函数呢?这是否会更新pom.xml文件内容?/test.sh:未找到第7行:xmlstarlet:命令。安装模块不是一个选项。这就是我为什么要香草bash的原因。那么它如何适合我的功能呢?这是否会更新pom.xml文件内容?/test.sh:未找到第7行:xmlstarlet:命令。安装模块不是一个选项。这就是为什么我要香草大餐。我会试试这个,谢谢!我的sed版本支持“-i”选项。yesI使用了第一个解决方案,在我修改了适用于我的mktemp调用(在编辑代码中)后,它工作得非常好。谢谢我更新了
mktemp
调用,在未指定DIR
值的情况下,不使用
--tmpdir
选项。我使用GNU
mktemp
coreutils
8.20),这是查找
$TMPDIR
环境变量。如果未设置,则使用
/tmp
。我猜这是不标准的,对你来说是失败的。代码是否像现在这样为您工作,还是您仍然需要进行调整?我希望我的答案尽可能方便携带。我会试试这个,谢谢!我的sed版本支持“-i”选项。yesI使用了第一个解决方案,在我修改了适用于我的mktemp调用(在编辑代码中)后,它工作得非常好。谢谢我更新了
mktemp
调用,在未指定DIR
值的情况下,不使用
--tmpdir
选项。我使用GNU
mktemp
coreutils
8.20),这是查找
$TMPDIR
环境变量。如果未设置,则使用
/tmp
。我猜这是不标准的,对你来说是失败的。代码是否像现在这样为您工作,还是您仍然需要进行调整?我希望我的答案尽可能便于携带。