split svnversion output in bash
I have this function, works fine, but I would like to rewrite it in bash. the problem is, I have too little knowledge of what's available in bash.
#!/usr/bin/开发者_如何学JAVApython
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()
what I would like is a similarly small bash function that I can invoke and that will set something (three variables? an array?) that I can use. if it's an array, I would really like it to be of fixed size (3).
This creates an array called "tuple" with three elements:
[[ $(svnversion .) =~ ([0-9]+):*([0-9]*)([A-Z]*) ]]
tuple[0]=${BASH_REMATCH[1]}
tuple[1]=${BASH_REMATCH[2]:-${tuple[0]}}
tuple[2]=${BASH_REMATCH[3]:-''}
Requires Bash 3.2 or greater. It may work in Bash >= 3 and < 3.2. Not portable to the Bourne shell, although it can be adapted for the Korn shell or the Z shell.
ksh
uses the .sh.match
array variable, for example: ${.sh.match[1]}
zsh
uses the match
array variable, for example: ${match[1]}
or you can do
setopt bashrematch ksharrays
to have it work with the Bash version exactly as above.
The brace substitutions should be the same for all three.
you can use this subroutine
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"
The following solution stores the values into the array arr[ ] to match your original tuple as closely as possible. After the if-else-fi
block you can do whatever you want with arr[0],arr[1], and arr[2]. I tried to match your post (and comment) as closely as possible. Also, I took the liberty to send the warning and notice messages to STDERR rather than STDOUT thinking you probably want to separate those.
#!/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"
Result without STDERR (sent to /dev/null)
$ ./svn_split.sh 2> /dev/null 1024 1024 1024 2000 1024 1024 M 1024 2000 MP 2000 1024 M
Result with 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
精彩评论