Add negative decimal input, regex for prefixes, bits per int detection
This commit is contained in:
102
bash/base.sh
102
bash/base.sh
@@ -14,6 +14,31 @@
|
|||||||
|
|
||||||
CMDNAME=${0##*/} # script name
|
CMDNAME=${0##*/} # script name
|
||||||
|
|
||||||
|
# some default values (blocks separator padchar)
|
||||||
|
# Attention: For output base 10, obase is 1
|
||||||
|
declare -i ibase=0 obase=0 padding=0 prefix=1 ogroup=0 intbits
|
||||||
|
|
||||||
|
# find out int size (bits) - suppose 2-complement, and 8 bits char
|
||||||
|
printf -v _b "%x" -1
|
||||||
|
(( intbits = ${#_b} * 4 ))
|
||||||
|
|
||||||
|
declare -rA _bases=( # -f/-b accepted values
|
||||||
|
[2]=2 [b]=2 [B]=2
|
||||||
|
[8]=8 [o]=8 [O]=8
|
||||||
|
[10]=10 [d]=10 [D]=10
|
||||||
|
[16]=16 [h]=16 [H]=16
|
||||||
|
[a]=-1 [g]=-1
|
||||||
|
)
|
||||||
|
declare -A _pad=( # group separator
|
||||||
|
[2]=" " [8]=" " [10]="," [16]=" "
|
||||||
|
)
|
||||||
|
declare -rA _ogroup=( # group size
|
||||||
|
[2]=8 [8]=3 [10]=3 [16]=4
|
||||||
|
)
|
||||||
|
declare -rA _oprefix=( # output prefix
|
||||||
|
[2]="2#" [8]="0" [10]="" [16]="0x"
|
||||||
|
)
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
printf "usage: %s [OPTIONS] [NUMBER]...\n" "$CMDNAME"
|
printf "usage: %s [OPTIONS] [NUMBER]...\n" "$CMDNAME"
|
||||||
printf "Use '%s -h' for more help\n" "$CMDNAME"
|
printf "Use '%s -h' for more help\n" "$CMDNAME"
|
||||||
@@ -29,6 +54,7 @@ usage: $CMDNAME [OPTIONS] [NUMBER]...
|
|||||||
-p, --padding 0-pad output on block boundary (implies -g)
|
-p, --padding 0-pad output on block boundary (implies -g)
|
||||||
-n, --noprefix remove base prefixes in output
|
-n, --noprefix remove base prefixes in output
|
||||||
-h, --help this help
|
-h, --help this help
|
||||||
|
-- end of options
|
||||||
|
|
||||||
$CMDNAME output the NUMBERS arguments in different bases. If no NUMBER is
|
$CMDNAME output the NUMBERS arguments in different bases. If no NUMBER is
|
||||||
given, standard input will be used.
|
given, standard input will be used.
|
||||||
@@ -45,9 +71,12 @@ INPUT NUMBER
|
|||||||
If input base is not specified, some prefixes are supported.
|
If input base is not specified, some prefixes are supported.
|
||||||
'b' or '2/' for binary, '0', 'o' or '8/' for octal, '0x', 'x' or
|
'b' or '2/' for binary, '0', 'o' or '8/' for octal, '0x', 'x' or
|
||||||
'16/' for hexadecimal, and 'd' or '10/' for decimal.
|
'16/' for hexadecimal, and 'd' or '10/' for decimal.
|
||||||
If no prefix, decimal is assumed.
|
If no above prefix is found, decimal is assumed.
|
||||||
|
Decimal input may be signed or unsigned, with limits imposed by current
|
||||||
|
Bash (here: $intbits bits).
|
||||||
|
|
||||||
OUTPUT
|
OUTPUT
|
||||||
|
Decimal output is always unsigned.
|
||||||
By default, the input number is shown converted in the 4 supported
|
By default, the input number is shown converted in the 4 supported
|
||||||
bases (16, 10, 8, 2, in this order), separated by one tab character.
|
bases (16, 10, 8, 2, in this order), separated by one tab character.
|
||||||
Without '-n' option, all output numbers but decimal will be prefixed:
|
Without '-n' option, all output numbers but decimal will be prefixed:
|
||||||
@@ -66,12 +95,12 @@ EXAMPLES
|
|||||||
$ $CMDNAME 0
|
$ $CMDNAME 0
|
||||||
0x0 0 0 2#0
|
0x0 0 0 2#0
|
||||||
|
|
||||||
$ $CMDNAME -n 2/100
|
|
||||||
4 4 4 100
|
|
||||||
|
|
||||||
$ $CMDNAME 123456
|
$ $CMDNAME 123456
|
||||||
0x1e240 123456 0361100 2#11110001001000000
|
0x1e240 123456 0361100 2#11110001001000000
|
||||||
|
|
||||||
|
$ $CMDNAME -n 2/100
|
||||||
|
4 4 4 100
|
||||||
|
|
||||||
$ $CMDNAME -n 0x1e240
|
$ $CMDNAME -n 0x1e240
|
||||||
1e240 123456 361100 11110001001000000
|
1e240 123456 361100 11110001001000000
|
||||||
|
|
||||||
@@ -79,6 +108,10 @@ EXAMPLES
|
|||||||
$ $CMDNAME -bng 0x1e240
|
$ $CMDNAME -bng 0x1e240
|
||||||
1 11100010 01000000
|
1 11100010 01000000
|
||||||
|
|
||||||
|
Negative input (decimal only):
|
||||||
|
$ $CMDNAME -x -- -1
|
||||||
|
0xffffffffffffffff
|
||||||
|
|
||||||
Input base indication, left padding binary output, no prefix:
|
Input base indication, left padding binary output, no prefix:
|
||||||
$ $CMDNAME -nbp -f8 361100
|
$ $CMDNAME -nbp -f8 361100
|
||||||
00000001 11100010 01000000
|
00000001 11100010 01000000
|
||||||
@@ -91,30 +124,13 @@ EXAMPLES
|
|||||||
Long options, with separator and padding:
|
Long options, with separator and padding:
|
||||||
$ $CMDNAME --to=16 --noprefix --padding --group=: 12345
|
$ $CMDNAME --to=16 --noprefix --padding --group=: 12345
|
||||||
0001:e240
|
0001:e240
|
||||||
|
|
||||||
|
TODO
|
||||||
|
Add option for signed/unsigned integer output.
|
||||||
|
Remove useless octal output ?
|
||||||
_EOF
|
_EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
# some default values (blocks separator padchar)
|
|
||||||
# Attention: For output base 10, obase is 1
|
|
||||||
declare -i ibase=0 obase=0 padding=0 prefix=1 ogroup=0
|
|
||||||
|
|
||||||
declare -rA _bases=(
|
|
||||||
[2]=2 [b]=2 [B]=2
|
|
||||||
[8]=8 [o]=8 [O]=8 [0]=8
|
|
||||||
[10]=10 [d]=10 [D]=10
|
|
||||||
[16]=16 [h]=16 [H]=16 [0x]=16
|
|
||||||
[a]=-1 [g]=-1
|
|
||||||
)
|
|
||||||
declare -A _pad=(
|
|
||||||
[2]=" " [8]=" " [10]="," [16]=" "
|
|
||||||
)
|
|
||||||
declare -rA _ogroup=(
|
|
||||||
[2]=8 [8]=3 [10]=3 [16]=4
|
|
||||||
)
|
|
||||||
declare -rA _oprefix=(
|
|
||||||
[2]="2#" [8]="0" [10]="" [16]="0x"
|
|
||||||
)
|
|
||||||
|
|
||||||
zero_pad() {
|
zero_pad() {
|
||||||
local n="$1" str="$2"
|
local n="$1" str="$2"
|
||||||
|
|
||||||
@@ -142,11 +158,16 @@ split() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bin() {
|
bin() {
|
||||||
local n bits=""
|
local str=""
|
||||||
for (( n = $1 ; n > 0 ; n >>= 1 )); do
|
local -i n dec="$1"
|
||||||
bits=$((n&1))$bits
|
|
||||||
|
# take care of negative numbers, as >> operator keeps the sign.
|
||||||
|
# 'intbits' is size of integer in bits in current shell.
|
||||||
|
for (( n = 0 ; dec && (n < intbits); n++ )); do
|
||||||
|
str="$(( dec & 1 ))$str"
|
||||||
|
(( dec >>= 1 ))
|
||||||
done
|
done
|
||||||
printf "%s\n" "${bits:-0}"
|
printf "%s\n" "${str:-0}"
|
||||||
}
|
}
|
||||||
|
|
||||||
hex() {
|
hex() {
|
||||||
@@ -213,8 +234,8 @@ parse_opts() {
|
|||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
# parse remaining arguments
|
# next are numbers to convert, if any
|
||||||
if (($# > 0)); then # type
|
if (($# > 0)); then
|
||||||
args=("$@")
|
args=("$@")
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -230,23 +251,20 @@ addprefix() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stripprefix() {
|
stripprefix() {
|
||||||
local number="$1"
|
[[ $1 =~ ^(0x|b|o|d|x|.*/) ]]
|
||||||
number=${number#0x}
|
printf "%s" "${1#"${BASH_REMATCH[1]}"}"
|
||||||
number=${number#[bodx]}
|
|
||||||
number=${number#*/}
|
|
||||||
printf "%s" "$number"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guessbase() {
|
guessbase() {
|
||||||
local input="$1"
|
local input="$1"
|
||||||
local -i base=0
|
local -i base=0
|
||||||
if [[ $input =~ ^b || $input =~ ^2/ ]]; then
|
if [[ $input =~ ^(b|2/) ]]; then
|
||||||
base=2
|
base=2
|
||||||
elif [[ $input =~ ^0x || $input =~ ^x || $input =~ ^16/ ]]; then
|
elif [[ $input =~ ^(0x|x|16/) ]]; then
|
||||||
base=16
|
base=16
|
||||||
elif [[ $input =~ ^0 || $input =~ ^o || $input =~ ^8/ ]]; then
|
elif [[ $input =~ ^(0|o|8/) ]]; then
|
||||||
base=8
|
base=8
|
||||||
elif [[ $input =~ ^d || $input =~ ^10/ ]]; then
|
elif [[ $input =~ ^(d|10/) ]]; then
|
||||||
base=10
|
base=10
|
||||||
fi
|
fi
|
||||||
return $(( base ? base : 10 ))
|
return $(( base ? base : 10 ))
|
||||||
@@ -261,7 +279,9 @@ doit() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
inum=$(stripprefix "$number")
|
inum=$(stripprefix "$number")
|
||||||
(( decval = "$base#$inum" )) # input value in decimal
|
# convert input value to decimal
|
||||||
|
(( base == 10 )) && (( decval = inum ))
|
||||||
|
(( base != 10 )) && (( decval = "$base#$inum" ))
|
||||||
|
|
||||||
# mask for desired output: 1=decimal, others are same as base
|
# mask for desired output: 1=decimal, others are same as base
|
||||||
if (( ! _obase )); then
|
if (( ! _obase )); then
|
||||||
|
Reference in New Issue
Block a user