如何在命令行中将值数组传递给shell脚本并在循环中传递建议

时间:2013-05-17 01:22:10

标签: bash shell svn awk

目标是根据版本号仅从svn log获取文件名。每个提交在svn注释中都有一个jira票号,因此通过查找jira票号来获得svn修订。

到目前为止,当我只提供一个jira票号时,脚本工作正常,但是当我提供多张jira票时,我需要让它工作。

  1. 此脚本的问题是输出仅包含ticket-2中的值。如何让输出包含ticket-1和ticket-2的值?

  2. 我需要一些关于如何将ticket-1和ticket-2作为参数传递给脚本而不是在脚本中分配它们的帮助?

  3. 代码:

    #!/bin/sh
    
    src_url=$1
    target_url=$2
    jira_ticket=("ticket-1 ticket-2")
    
    for i in $jira_ticket; do
        revs=(`svn log $1 --limit 10 | grep -B 2 $i | grep "^r" | cut -d"r" -f2 | cut -d" " -   f1|sort -r`)
    done
    
    for revisions in ${!revs[*]}; do
        files=(`svn log -v  $1 -r ${revs[$revisions]} | awk '$1~/^[AMD]$/{for(i=2;i<=NF;i++)print $i}'`)
        for (( i = 0; i < ${#files[@]}; i++ )); do
            echo "${files[$i]} @" ${revs[$revisions]} " will be merged."
        done
    done
    

1 个答案:

答案 0 :(得分:4)

TL;博士

因为第二个循环(处理revs)在第一个循环之外(设置revs)。将第二个循环移动到第一个循环内以解决此问题。

详细维修

这个脚本需要一些严肃的修复。

  • 数组jira_ticket声明错误 - 应为jira_ticket=("ticket-1" "ticket-2")
  • 要循环遍历数组中的每个元素,请使用"${array[@]}"(引号对于避免意外的单词拆分非常重要,使用@代替*会将扩展拆分为一个每个元素的单词,这是你所追求的)。 $array相当于${array[0]}
  • 循环数组键的原理相同:说"${!array[@]}"而不是${!array[*]}
  • 为什么在循环覆盖值而不需要密钥时循环键?
  • 循环中的变量赋值不能保证传播出来(它们可能在这里,但在管道中发生奇怪的事情等等。)
  • 您是不是要在第一个循环中执行第二个循环,以使用revs的每个副本? (因为它只是处理最后一个副本。)
  • 引用所有变量扩展("$1",而不是$1)。
  • 使用现代命令替换语法$(command)而不是反引号。它不易出错。
  • 您需要正确设置IFS以正确拆分命令替换结果。我想你是在$'\n'的IFS之后; 我可能错了

将票证作为参数传递

在处理shift后使用$1删除$1,然后将剩下的所有内容分配给jira_tickets数组。

脚本,尽我所能修复:

#!/bin/sh
# First argument is the source URL; remaining args are ticket numbers
src_url="$1"; shift
#target_url="$2"; shift # Never used

# Handy syntax hint: `for i in "$@"; do` == `for i; do`
for ticket; do
  # Fixed below $1 to be $src_url
  revs=($(IFS=$'\n'; svn log "$src_url" --limit 10 | grep -B 2 "$ticket" | grep "^r" | cut -d"r" -f2 | cut -d" " - f1 | sort -r))

  for revision in "${revs[@]}"; do # I think you meant to loop over the values here, not the keys
    files=($(IFS=$'\n'; svn log -v "$src_url" -r "$revision"  | awk '$1~/^[AMD]$/{for(i=2;i<=NF;i++)print $i}'))

    for file in "${files[@]}"; do # Think you wanted to loop over the values here too
      echo "$file @ $revision will be merged."
    done
  done
done