在bash中分割svnversion输出
我有一个函数,运行得很好,但我想把它改写成bash脚本。问题是,我对bash的知识太少了,不太清楚里面有什么可用的东西。
#!/usr/bin/python
def parse_svnversion(value):
"""split the output of svnversion into its three components
given a string that looks like the output of the command
svnversion, returns the 3-tuple (low, high, flags)
>>> parse_svnversion('1024')
(1024, 1024, '')
>>> parse_svnversion('1024:2000')
(1024, 2000, '')
>>> parse_svnversion('1024M')
(1024, 1024, 'M')
>>> parse_svnversion('1024:2000MP')
(1024, 2000, 'MP')
"""
values = filter(lambda x: x.isdigit() or x==':', value).split(':')
return int(values[0]), int(values[-1]), filter(str.isalpha, value)
if __name__ == '__main__':
import doctest
doctest.testmod()
我希望能有一个类似的小bash函数,我可以调用它,然后它会设置一些东西(比如三个变量?一个数组?)让我使用。如果是数组的话,我希望它的大小是固定的(3个元素)。
3 个回答
0
下面这个解决方案会把值存储到数组 arr[ ] 中,尽量和你原来的元组(tuple)保持一致。在 if-else-fi
这个代码块之后,你可以随意使用 arr[0]、arr[1] 和 arr[2]。我尽量按照你的帖子(和评论)来做得很接近。另外,我也主动把警告和通知信息发送到了 STDERR,而不是 STDOUT,因为我觉得你可能想把它们分开处理。
#!/bin/bash
parse_svnversion()
{
if [[ "$1" = *:* ]]; then
arr[0]=${1%:*}
arr[2]=${1//[0-9:]/}
tmp_arr[1]=${1#*:}
arr[1]=${tmp_arr[1]//${arr[2]}/}
else
arr[2]=${1//[0-9:]/}
arr[0]=${1//${arr[2]}/}
arr[1]=${arr[0]}
fi
echo ${arr[@]}
head_rev=$( (( ${arr[0]} > ${arr[1]} )) && echo ${arr[0]} || echo ${arr[1]} )
echo "Notice: head revision is $head_rev" >&2
if (( ${arr[1]} < ${arr[0]} )); then
echo "Warning: you're working with mixed revisions" >&2
fi
if [[ -n ${arr[2]} ]]; then
echo "Warning: there are flags" >&2
fi
}
parse_svnversion "1024"
parse_svnversion "1024:2000"
parse_svnversion "1024M"
parse_svnversion "1024:2000MP"
parse_svnversion "2000:1024M"
没有 STDERR 的结果(发送到 /dev/null)
$ ./svn_split.sh 2> /dev/null 1024 1024 1024 2000 1024 1024 M 1024 2000 MP 2000 1024 M
有 STDERR 的结果
$ ./svn_split.sh 1024 1024 Notice: head revision is 1024 1024 2000 Notice: head revision is 2000 1024 1024 M Notice: head revision is 1024 Warning: there are flags 1024 2000 MP Notice: head revision is 2000 Warning: there are flags 2000 1024 M Notice: head revision is 2000 Warning: you're working with mixed revisions Warning: there are flags
1
你可以使用这个子程序
parsesvn(){
toparse="$1"
num=${toparse%%[A-Z]*}
alpha=${toparse##*[0-9]}
IFS=":"
set -- $num
for i in $@
do
printf "%s " $i
done
if [ ! -z "$alpha" ];then
printf "%s" "$alpha"
fi
}
# main #
var=$(parsesvn "1024:2000")
set -- $var
if [ "$1" -lt "$2" ];then
echo "ok"
greater=$2
else
echo "LHS: $1 greater than RHS: $2"
fi
echo "greater is $greater"
4
这段代码创建了一个叫做“tuple”的数组,里面有三个元素:
[[ $(svnversion .) =~ ([0-9]+):*([0-9]*)([A-Z]*) ]]
tuple[0]=${BASH_REMATCH[1]}
tuple[1]=${BASH_REMATCH[2]:-${tuple[0]}}
tuple[2]=${BASH_REMATCH[3]:-''}
这个功能需要使用Bash 3.2或更高版本。它可能在Bash 3到3.2之间的版本也能工作,但不适用于Bourne shell,虽然可以调整一下让它在Korn shell或Z shell中使用。
ksh
使用的是.sh.match
这个数组变量,比如说:${.sh.match[1]}
zsh
使用的是match
这个数组变量,比如说:${match[1]}
,或者你也可以这样做:
setopt bashrematch ksharrays
这样就能让它在Bash版本中和上面一样工作。
大括号的替换在这三种情况下应该是一样的。