Add bash arithmetic section to notes
This commit is contained in:
parent
2331cc55ac
commit
8f06577f87
79
notes/shell/bash_arithmetic.md
Normal file
79
notes/shell/bash_arithmetic.md
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Working with numbers in bash
|
||||||
|
Bash interprets everything by default as a string, however it can also work with
|
||||||
|
numbers, just be careful with your conditional operators
|
||||||
|
|
||||||
|
## Storing numbers
|
||||||
|
`declare` and `local` both can make integer variables with the `-i` flag
|
||||||
|
|
||||||
|
```bash
|
||||||
|
declare -i a=2
|
||||||
|
|
||||||
|
f () { local -i a=3 ;}
|
||||||
|
```
|
||||||
|
|
||||||
|
Variables can be manipulated in double parenthesis, very similar to c/python.
|
||||||
|
Use `$(())` to return the value instead. Edges and centers seem whitespace
|
||||||
|
insensitive. No need to `$` in front of variables inside `(())`
|
||||||
|
|
||||||
|
Work as expected: `+ - * %`
|
||||||
|
Exponent: `**`
|
||||||
|
Floored division: `/`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
declare -i a=2 b=3 # Multiple on the same line are fine
|
||||||
|
|
||||||
|
(( a++ )) # a == 3
|
||||||
|
(( a+=b )) # a == 6
|
||||||
|
(( a = 2 )) # a == 2
|
||||||
|
((a=4+b)) # a == 7
|
||||||
|
(( a = 4 + b )) # Spacing is optional, same as above
|
||||||
|
|
||||||
|
declare -i c=$((a**b + 4)) # c == 7**3 + 4 == 347
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using numbers
|
||||||
|
Conditionals are different for numbers in bash. Mapping c to bash:
|
||||||
|
|
||||||
|
```
|
||||||
|
C | Bash
|
||||||
|
----|-----
|
||||||
|
== | -eq
|
||||||
|
!= | -ne
|
||||||
|
> | -gt
|
||||||
|
< | -lt
|
||||||
|
>= | -ge
|
||||||
|
<= | -le
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
declare -i a=3 b=2
|
||||||
|
|
||||||
|
if [[ $((a**b)) -ge 1000 ]]; then
|
||||||
|
echo "Exponentiation with ${a}^${b} is pretty big"
|
||||||
|
elif [[ $a -lt $b ]]; then
|
||||||
|
echo "$a is smaller than $b"
|
||||||
|
else
|
||||||
|
echo "$a isn't smaller than $b"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "You rolled a: $(( RANDOM % 6 + 1 )) on a 6 sided dice"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Floats
|
||||||
|
Bash has no support for floats, don't even try. If you need floats, use awk,
|
||||||
|
which has full support. To still sort of use rational numbers in bash, store a
|
||||||
|
numerator and denominator, then pass both to awk when you need the float
|
||||||
|
|
||||||
|
```bash
|
||||||
|
declare -i num_1=4 denom_1=9
|
||||||
|
declare -i num_2=2 denom_2=9
|
||||||
|
|
||||||
|
(( num_1 += num_2 ))
|
||||||
|
|
||||||
|
awk -v n1=$num_1 -v d1=$denom_1 -v n2=$num_2 -v d2=$denom_2 \
|
||||||
|
'BEGIN { printf "%.2f\n", n1/d1 + n2/d2 }'
|
||||||
|
```
|
||||||
|
|
||||||
|
Bash has floored division `/` and remainders `%`, though the awk approach is
|
||||||
|
easier. Note awk's syntax is identical to c, so it uses `^` for exponentiation
|
||||||
|
and the standard `==`, `<=`... for comparison
|
|
@ -35,11 +35,15 @@ visual mode
|
||||||
:21 Goes to line 21. ^ and $ are for the first and last line
|
:21 Goes to line 21. ^ and $ are for the first and last line
|
||||||
:10,20d Deletes lines 10 through 20, inclusive on both ends
|
:10,20d Deletes lines 10 through 20, inclusive on both ends
|
||||||
:u[ndo] Undoes the last action
|
:u[ndo] Undoes the last action
|
||||||
|
:mark a Makes a mark at a. From vim
|
||||||
|
:ka Also makes a mark at a. From ex
|
||||||
|
:'a Go to mark a
|
||||||
:g/re/p Globally exectute a command on lines with /re/
|
:g/re/p Globally exectute a command on lines with /re/
|
||||||
:v/re/p Inverse of :g. Executes on all lines without /re/
|
:v/re/p Inverse of :g. Executes on all lines without /re/
|
||||||
:3,6co$ Copy lines [3,6] to the end of the document
|
:3,6co$ Copy lines [3,6] to the end of the document
|
||||||
:3m6 Move line 3 to line 6
|
:3m6 Move line 3 to line 6
|
||||||
:z=3 Pretty print lines in [-2,+2]
|
:z=3 Pretty print lines in [-2,+2]
|
||||||
|
:norm! @l Execute keystrokes, if all else fails
|
||||||
```
|
```
|
||||||
|
|
||||||
Several commands can be chained with `|`, similar to `;` in bash
|
Several commands can be chained with `|`, similar to `;` in bash
|
||||||
|
|
Loading…
Reference in a new issue