Added arithmetic operators

This commit is contained in:
Dylan Araps
2018-06-21 18:00:05 +10:00
parent b5a2ad5e0a
commit 955370b5ce
11 changed files with 621 additions and 497 deletions

View File

@@ -93,7 +93,13 @@ See something that is incorrectly described, buggy or outright wrong? Open an is
* [BRACE EXPANSION](#brace-expansion) * [BRACE EXPANSION](#brace-expansion)
* [Ranges](#ranges) * [Ranges](#ranges)
* [String Lists](#string-lists) * [String Lists](#string-lists)
* [ARITHMETIC](#arithmetic) * [ARITHMETIC OPERATORS](#arithmetic-operators)
* [Assignment](#assignment)
* [Arithmetic](#arithmetic)
* [Bitwise](#bitwise)
* [Logical](#logical)
* [Miscellaneous](#miscellaneous)
* [ARITHMETIC](#arithmetic-1)
* [Simpler syntax to set variables](#simpler-syntax-to-set-variables) * [Simpler syntax to set variables](#simpler-syntax-to-set-variables)
* [Ternary Tests](#ternary-tests) * [Ternary Tests](#ternary-tests)
* [TRAPS](#traps) * [TRAPS](#traps)
@@ -1189,6 +1195,65 @@ echo {apples,oranges,pears,grapes}
rm -rf ~/Downloads/{Movies,Music,ISOS} rm -rf ~/Downloads/{Movies,Music,ISOS}
``` ```
<!-- CHAPTER END -->
<!-- CHAPTER START -->
# ARITHMETIC OPERATORS
## Assignment
| Operators | What does it do? |
| --------- | ---------------- |
| `=` | Initialize or change the value of a variable.
## Arithmetic
| Operators | What does it do? |
| --------- | ---------------- |
| `+` | Addition
| `-` | Subtraction
| `*` | Multiplication
| `/` | Division
| `**` | Exponentiation
| `%` | Modulo
| `+=` | Plus-Equal (*Increment a variable.*)
| `-=` | Minus-Equal (*Decrement a variable.*)
| `*=` | Times-Equal (*Multiply a variable.*)
| `/=` | Slash-Equal (*Divide a variable.*)
| `%=` | Mod-Equal (*Remainder of dividing a variable.*)
## Bitwise
| Operators | What does it do? |
| --------- | ---------------- |
| `<<` | Bitwise Left Shift
| `<<=` | Left-Shift-Equal
| `>>` | Bitwise Right Shift
| `>>=` | Right-Shift-Equal
| `&` | Bitwise AND
| `&=` | Bitwise AND-Equal
| `\|` | Bitwise OR
| `\|=` | Bitwise OR-Equal
| `~` | Bitwise NOT
| `^` | Bitwise XOR
| `^=` | Bitwise XOR-Equal
## Logical
| Operators | What does it do? |
| --------- | ---------------- |
| `!` | NOT
| `&&` | AND
| `\|\|` | OR
## Miscellaneous
| Operators | What does it do? | Example |
| --------- | ---------------- | ------- |
| `,` | Comma Separator | `((a=1,b=2,c=3))`
<!-- CHAPTER END --> <!-- CHAPTER END -->
<!-- CHAPTER START --> <!-- CHAPTER START -->

View File

@@ -16,3 +16,4 @@ chapter14.txt
chapter15.txt chapter15.txt
chapter16.txt chapter16.txt
chapter17.txt chapter17.txt
chapter18.txt

View File

@@ -1,31 +1,58 @@
# ARITHMETIC
## Simpler syntax to set variables # ARITHMETIC OPERATORS
```shell ## Assignment
# Simple math
((var=1+2))
# Decrement/Increment variable | Operators | What does it do? |
((var++)) | --------- | ---------------- |
((var--)) | `=` | Initialize or change the value of a variable.
((var+=1))
((var-=1))
# Using variables ## Arithmetic
((var=var2*arr[2]))
```
## Ternary Tests | Operators | What does it do? |
| --------- | ---------------- |
| `+` | Addition
| `-` | Subtraction
| `*` | Multiplication
| `/` | Division
| `**` | Exponentiation
| `%` | Modulo
| `+=` | Plus-Equal (*Increment a variable.*)
| `-=` | Minus-Equal (*Decrement a variable.*)
| `*=` | Times-Equal (*Multiply a variable.*)
| `/=` | Slash-Equal (*Divide a variable.*)
| `%=` | Mod-Equal (*Remainder of dividing a variable.*)
## Bitwise
| Operators | What does it do? |
| --------- | ---------------- |
| `<<` | Bitwise Left Shift
| `<<=` | Left-Shift-Equal
| `>>` | Bitwise Right Shift
| `>>=` | Right-Shift-Equal
| `&` | Bitwise AND
| `&=` | Bitwise AND-Equal
| `\|` | Bitwise OR
| `\|=` | Bitwise OR-Equal
| `~` | Bitwise NOT
| `^` | Bitwise XOR
| `^=` | Bitwise XOR-Equal
## Logical
| Operators | What does it do? |
| --------- | ---------------- |
| `!` | NOT
| `&&` | AND
| `\|\|` | OR
## Miscellaneous
| Operators | What does it do? | Example |
| --------- | ---------------- | ------- |
| `,` | Comma Separator | `((a=1,b=2,c=3))`
```shell
# Set the value of var to var2 if var2 is greater than var.
# var: variable to set.
# var2>var: Condition to test.
# ?var2: If the test succeeds.
# :var: If the test fails.
((var=var2>var?var2:var))
```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,42 +1,30 @@
# TRAPS # ARITHMETIC
Traps allow a script to execute code on various signals. In [pxltrm](https://github.com/dylanaraps/pxltrm) (*a pixel art editor written in bash*) traps are used to redraw the user interface on window resize. Another use case is cleaning up temporary files on script exit. ## Simpler syntax to set variables
Traps should be added near the start of scripts so any early errors are also caught.
**NOTE:** For a full list of signals, see `trap -l`.
## Do something on script exit
```shell ```shell
# Clear screen on script exit. # Simple math
trap 'printf \\e[2J\\e[H\\e[m' EXIT ((var=1+2))
# Decrement/Increment variable
((var++))
((var--))
((var+=1))
((var-=1))
# Using variables
((var=var2*arr[2]))
``` ```
## Ignore terminal interrupt (CTRL+C, SIGINT) ## Ternary Tests
```shell ```shell
trap '' INT # Set the value of var to var2 if var2 is greater than var.
``` # var: variable to set.
# var2>var: Condition to test.
## React to window resize. # ?var2: If the test succeeds.
# :var: If the test fails.
```shell ((var=var2>var?var2:var))
# Call a function on window resize.
trap 'code_here' SIGWINCH
```
## Do something before every command.
```shell
trap 'code_here' DEBUG
```
## Do something when a shell function or a sourced file finishes executing
```shell
trap 'code_here' RETURN
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,13 +1,42 @@
# PERFORMANCE # TRAPS
## Disable Unicode Traps allow a script to execute code on various signals. In [pxltrm](https://github.com/dylanaraps/pxltrm) (*a pixel art editor written in bash*) traps are used to redraw the user interface on window resize. Another use case is cleaning up temporary files on script exit.
If unicode is not required, it can be disabled for a performance increase. Results may vary however there have been noticeable improvements in [neofetch](https://github.com/dylanaraps/neofetch) and other programs. Traps should be added near the start of scripts so any early errors are also caught.
**NOTE:** For a full list of signals, see `trap -l`.
## Do something on script exit
```shell ```shell
# Disable unicode. # Clear screen on script exit.
LC_ALL=C trap 'printf \\e[2J\\e[H\\e[m' EXIT
LANG=C ```
## Ignore terminal interrupt (CTRL+C, SIGINT)
```shell
trap '' INT
```
## React to window resize.
```shell
# Call a function on window resize.
trap 'code_here' SIGWINCH
```
## Do something before every command.
```shell
trap 'code_here' DEBUG
```
## Do something when a shell function or a sourced file finishes executing
```shell
trap 'code_here' RETURN
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,51 +1,13 @@
# OBSOLETE SYNTAX # PERFORMANCE
## Shebang ## Disable Unicode
Use `#!/usr/bin/env bash` instead of `#!/bin/bash`. If unicode is not required, it can be disabled for a performance increase. Results may vary however there have been noticeable improvements in [neofetch](https://github.com/dylanaraps/neofetch) and other programs.
- The former searches the user's `PATH` to find the `bash` binary.
- The latter assumes it is always installed to `/bin/` which can cause issues.
```shell ```shell
# Right: # Disable unicode.
LC_ALL=C
#!/usr/bin/env bash LANG=C
# Wrong:
#!/bin/bash
```
## Command Substitution
Use `$()` instead of `` ` ` ``.
```shell
# Right.
var="$(command)"
# Wrong.
var=`command`
# $() can easily be nested whereas `` cannot.
var="$(command "$(command)")"
```
## Function Declaration
Do not use the `function` keyword, it reduces compatibility with older versions of `bash`.
```shell
# Right.
do_something() {
# ...
}
# Wrong.
function do_something() {
# ...
}
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,93 +1,51 @@
# INTERNAL VARIABLES # OBSOLETE SYNTAX
## Get the location to the `bash` binary ## Shebang
Use `#!/usr/bin/env bash` instead of `#!/bin/bash`.
- The former searches the user's `PATH` to find the `bash` binary.
- The latter assumes it is always installed to `/bin/` which can cause issues.
```shell ```shell
"$BASH" # Right:
#!/usr/bin/env bash
# Wrong:
#!/bin/bash
``` ```
## Get the version of the current running `bash` process ## Command Substitution
Use `$()` instead of `` ` ` ``.
```shell ```shell
# As a string. # Right.
"$BASH_VERSION" var="$(command)"
# As an array. # Wrong.
"${BASH_VERSINFO[@]}" var=`command`
# $() can easily be nested whereas `` cannot.
var="$(command "$(command)")"
``` ```
## Open the user's preferred text editor ## Function Declaration
Do not use the `function` keyword, it reduces compatibility with older versions of `bash`.
```shell ```shell
"$EDITOR" "$file" # Right.
do_something() {
# ...
}
# NOTE: This variable may be empty, set a fallback value. # Wrong.
"${EDITOR:-vi}" "$file" function do_something() {
``` # ...
}
## Get the name of the current function
```shell
# Current function.
"${FUNCNAME[0]}"
# Parent function.
"${FUNCNAME[1]}"
# So on and so forth.
"${FUNCNAME[2]}"
"${FUNCNAME[3]}"
# All functions including parents.
"${FUNCNAME[@]}"
```
## Get the host-name of the system
```shell
"$HOSTNAME"
# NOTE: This variable may be empty.
# Optionally set a fallback to the hostname command.
"${HOSTNAME:-$(hostname)}"
```
## Get the architecture of the Operating System
```shell
"$HOSTTYPE"
```
## Get the name of the Operating System / Kernel
This can be used to add conditional support for different Operating
Systems without needing to call `uname`.
```shell
"$OSTYPE"
```
## Get the current working directory
This is an alternative to the `pwd` built-in.
```shell
"$PWD"
```
## Get the number of seconds the script has been running
```shell
"$SECONDS"
```
## Get a pseudorandom integer
Each time `$RANDOM` is used, a different integer between `0` and `32767` is returned. This variable should not be used for anything related to security (*this includes encryption keys etc*).
```shell
"$RANDOM"
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,78 +1,93 @@
# INFORMATION ABOUT THE TERMINAL # INTERNAL VARIABLES
## Get the terminal size in lines and columns (*from a script*) ## Get the location to the `bash` binary
This is handy when writing scripts in pure bash and `stty`/`tput` cant be
called.
**Example Function:**
```sh
get_term_size() {
# Usage: get_term_size
# (:;:) is a micro sleep to ensure the variables are
# exported immediately.
shopt -s checkwinsize; (:;:)
printf '%s\n' "$LINES $COLUMNS"
}
```
**Example Usage:**
```shell ```shell
# Output: LINES COLUMNS "$BASH"
$ get_term_size
15 55
``` ```
## Get the terminal size in pixels ## Get the version of the current running `bash` process
**CAVEAT**: This does not work in some terminal emulators.
**Example Function:**
```sh
get_window_size() {
# Usage: get_window_size
printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}"
IFS=';t' read -d t -t 0.05 -sra term_size
printf '%s\n' "${term_size[1]}x${term_size[2]}"
}
```
**Example Usage:**
```shell ```shell
# Output: WIDTHxHEIGHT # As a string.
$ get_window_size "$BASH_VERSION"
1200x800
# Output (fail): # As an array.
$ get_window_size "${BASH_VERSINFO[@]}"
x
``` ```
## Get the current cursor position ## Open the user's preferred text editor
This is useful when creating a TUI in pure bash.
**Example Function:**
```sh
get_cursor_pos() {
# Usage: get_cursor_pos
IFS='[;' read -p $'\e[6n' -d R -rs _ y x _
printf '%s\n' "$x $y"
}
```
**Example Usage:**
```shell ```shell
# Output: X Y "$EDITOR" "$file"
$ get_cursor_pos
1 8 # NOTE: This variable may be empty, set a fallback value.
"${EDITOR:-vi}" "$file"
```
## Get the name of the current function
```shell
# Current function.
"${FUNCNAME[0]}"
# Parent function.
"${FUNCNAME[1]}"
# So on and so forth.
"${FUNCNAME[2]}"
"${FUNCNAME[3]}"
# All functions including parents.
"${FUNCNAME[@]}"
```
## Get the host-name of the system
```shell
"$HOSTNAME"
# NOTE: This variable may be empty.
# Optionally set a fallback to the hostname command.
"${HOSTNAME:-$(hostname)}"
```
## Get the architecture of the Operating System
```shell
"$HOSTTYPE"
```
## Get the name of the Operating System / Kernel
This can be used to add conditional support for different Operating
Systems without needing to call `uname`.
```shell
"$OSTYPE"
```
## Get the current working directory
This is an alternative to the `pwd` built-in.
```shell
"$PWD"
```
## Get the number of seconds the script has been running
```shell
"$SECONDS"
```
## Get a pseudorandom integer
Each time `$RANDOM` is used, a different integer between `0` and `32767` is returned. This variable should not be used for anything related to security (*this includes encryption keys etc*).
```shell
"$RANDOM"
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,147 +1,78 @@
# CONVERSION # INFORMATION ABOUT THE TERMINAL
## Convert a hex color to RGB ## Get the terminal size in lines and columns (*from a script*)
This is handy when writing scripts in pure bash and `stty`/`tput` cant be
called.
**Example Function:** **Example Function:**
```sh ```sh
hex_to_rgb() { get_term_size() {
# Usage: hex_to_rgb "#FFFFFF" # Usage: get_term_size
((r=16#${1:1:2}))
((g=16#${1:3:2}))
((b=16#${1:5:6}))
printf '%s\n' "$r $g $b" # (:;:) is a micro sleep to ensure the variables are
# exported immediately.
shopt -s checkwinsize; (:;:)
printf '%s\n' "$LINES $COLUMNS"
} }
``` ```
**Example Usage:** **Example Usage:**
```shell ```shell
$ hex_to_rgb "#FFFFFF" # Output: LINES COLUMNS
255 255 255 $ get_term_size
15 55
``` ```
## Get the terminal size in pixels
## Convert an RGB color to hex **CAVEAT**: This does not work in some terminal emulators.
**Example Function:** **Example Function:**
```sh ```sh
rgb_to_hex() { get_window_size() {
# Usage: rgb_to_hex "r" "g" "b" # Usage: get_window_size
printf '#%02x%02x%02x\n' "$1" "$2" "$3" printf '%b' "${TMUX:+\\ePtmux;\\e}\\e[14t${TMUX:+\\e\\\\}"
IFS=';t' read -d t -t 0.05 -sra term_size
printf '%s\n' "${term_size[1]}x${term_size[2]}"
} }
``` ```
**Example Usage:** **Example Usage:**
```shell ```shell
$ rgb_to_hex "255" "255" "255" # Output: WIDTHxHEIGHT
#FFFFFF $ get_window_size
1200x800
# Output (fail):
$ get_window_size
x
``` ```
## Get the current cursor position
# CODE GOLF This is useful when creating a TUI in pure bash.
## Shorter `for` loop syntax **Example Function:**
```shell ```sh
# Tiny C Style. get_cursor_pos() {
for((;i++<10;)){ echo "$i";} # Usage: get_cursor_pos
IFS='[;' read -p $'\e[6n' -d R -rs _ y x _
# Undocumented method. printf '%s\n' "$x $y"
for i in {1..10};{ echo "$i";}
# Expansion.
for i in {1..10}; do echo "$i"; done
# C Style.
for((i=0;i<=10;i++)); do echo "$i"; done
```
## Shorter infinite loops
```shell
# Normal method
while :; do echo hi; done
# Shorter
for((;;)){ echo hi;}
```
## Shorter function declaration
```shell
# Normal method
f(){ echo hi;}
# Using a subshell
f()(echo hi)
# Using arithmetic
# This can be used to assign integer values.
# Example: f a=1
# f a++
f()(($1))
# Using tests, loops etc.
# NOTE: while, until, case, (()), [[]] can also be used.
f()if true; then echo "$1"; fi
f()for i in "$@"; do echo "$i"; done
```
## Shorter `if` syntax
```shell
# One line
# Note: The 3rd statement may run when the 1st is true
[[ "$var" == hello ]] && echo hi || echo bye
[[ "$var" == hello ]] && { echo hi; echo there; } || echo bye
# Multi line (no else, single statement)
# Note: The exit status may not be the same as with an if statement
[[ "$var" == hello ]] && \
echo hi
# Multi line (no else)
[[ "$var" == hello ]] && {
echo hi
# ...
} }
``` ```
## Simpler `case` statement to set variable **Example Usage:**
The `:` built-in can be used to avoid repeating `variable=` in a case statement. The `$_` variable stores the last argument of the last command. `:` always succeeds so it can be used to store the variable value.
```shell ```shell
# Modified snippet from Neofetch. # Output: X Y
case "$OSTYPE" in $ get_cursor_pos
"darwin"*) 1 8
: "MacOS"
;;
"linux"*)
: "Linux"
;;
*"bsd"* | "dragonfly" | "bitrig")
: "BSD"
;;
"cygwin" | "msys" | "win32")
: "Windows"
;;
*)
printf '%s\n' "Unknown OS detected, aborting..." >&2
exit 1
;;
esac
# Finally, set the variable.
os="$_"
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

View File

@@ -1,189 +1,147 @@
# OTHER # CONVERSION
## Use `read` as an alternative to the `sleep` command ## Convert a hex color to RGB
Surprisingly, `sleep` is an external command and not a `bash` built-in.
**CAVEAT:** Requires `bash` 4+
**Example Function:** **Example Function:**
```sh ```sh
read_sleep() { hex_to_rgb() {
# Usage: sleep 1 # Usage: hex_to_rgb "#FFFFFF"
# sleep 0.2 ((r=16#${1:1:2}))
read -rst "${1:-1}" -N 999 ((g=16#${1:3:2}))
((b=16#${1:5:6}))
printf '%s\n' "$r $g $b"
} }
``` ```
**Example Usage:** **Example Usage:**
```shell ```shell
read_sleep 1 $ hex_to_rgb "#FFFFFF"
read_sleep 0.1 255 255 255
read_sleep 30
``` ```
## Check if a program is in the user's PATH
```shell ## Convert an RGB color to hex
# There are 3 ways to do this and either one can be used.
type -p executable_name &>/dev/null
hash executable_name &>/dev/null
command -v executable_name &>/dev/null
# As a test.
if type -p executable_name &>/dev/null; then
# Program is in PATH.
fi
# Inverse.
if ! type -p executable_name &>/dev/null; then
# Program is not in PATH.
fi
# Example (Exit early if program is not installed).
if ! type -p convert &>/dev/null; then
printf '%s\n' "error: convert is not installed, exiting..."
exit 1
fi
```
## Get the current date using `strftime`
Bashs `printf` has a built-in method of getting the date which can be used in place of the `date` command.
**CAVEAT:** Requires `bash` 4+
**Example Function:** **Example Function:**
```sh ```sh
date() { rgb_to_hex() {
# Usage: date "format" # Usage: rgb_to_hex "r" "g" "b"
# See: 'man strftime' for format. printf '#%02x%02x%02x\n' "$1" "$2" "$3"
printf "%($1)T\\n" "-1"
} }
``` ```
**Example Usage:** **Example Usage:**
```shell ```shell
# Using above function. $ rgb_to_hex "255" "255" "255"
$ date "%a %d %b - %l:%M %p" #FFFFFF
Fri 15 Jun - 10:00 AM
# Using printf directly.
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
Fri 15 Jun - 10:00 AM
# Assigning a variable using printf.
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
$ printf '%s\n' "$date"
Fri 15 Jun - 10:00 AM
``` ```
## Generate a UUID V4
**Example Function:** # CODE GOLF
```sh ## Shorter `for` loop syntax
uuid() {
# Usage: uuid
C="89ab"
for ((N=0;N<16;++N)); do ```shell
B="$((RANDOM%256))" # Tiny C Style.
for((;i++<10;)){ echo "$i";}
case "$N" in # Undocumented method.
6) printf '4%x' "$((B%16))" ;; for i in {1..10};{ echo "$i";}
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
3|5|7|9) # Expansion.
printf '%02x-' "$B" for i in {1..10}; do echo "$i"; done
;;
*) # C Style.
printf '%02x' "$B" for((i=0;i<=10;i++)); do echo "$i"; done
;; ```
esac
done
printf '\n' ## Shorter infinite loops
```shell
# Normal method
while :; do echo hi; done
# Shorter
for((;;)){ echo hi;}
```
## Shorter function declaration
```shell
# Normal method
f(){ echo hi;}
# Using a subshell
f()(echo hi)
# Using arithmetic
# This can be used to assign integer values.
# Example: f a=1
# f a++
f()(($1))
# Using tests, loops etc.
# NOTE: while, until, case, (()), [[]] can also be used.
f()if true; then echo "$1"; fi
f()for i in "$@"; do echo "$i"; done
```
## Shorter `if` syntax
```shell
# One line
# Note: The 3rd statement may run when the 1st is true
[[ "$var" == hello ]] && echo hi || echo bye
[[ "$var" == hello ]] && { echo hi; echo there; } || echo bye
# Multi line (no else, single statement)
# Note: The exit status may not be the same as with an if statement
[[ "$var" == hello ]] && \
echo hi
# Multi line (no else)
[[ "$var" == hello ]] && {
echo hi
# ...
} }
``` ```
**Example Usage:** ## Simpler `case` statement to set variable
The `:` built-in can be used to avoid repeating `variable=` in a case statement. The `$_` variable stores the last argument of the last command. `:` always succeeds so it can be used to store the variable value.
```shell ```shell
$ uuid # Modified snippet from Neofetch.
d5b6c731-1310-4c24-9fe3-55d556d44374 case "$OSTYPE" in
``` "darwin"*)
: "MacOS"
;;
## Progress bars "linux"*)
: "Linux"
;;
This is a simple way of drawing progress bars without needing a for loop *"bsd"* | "dragonfly" | "bitrig")
in the function itself. : "BSD"
;;
**Example Function:** "cygwin" | "msys" | "win32")
: "Windows"
;;
```sh *)
bar() { printf '%s\n' "Unknown OS detected, aborting..." >&2
# Usage: bar 1 10 exit 1
# ^----- Elapsed Percentage (0-100). ;;
# ^-- Total length in chars. esac
((elapsed=$1*$2/100))
# Create the bar with spaces. # Finally, set the variable.
printf -v prog "%${elapsed}s" os="$_"
printf -v total "%$(($2-elapsed))s"
printf '%s\r' "[${prog// /-}${total}]"
}
```
**Example Usage:**
```shell
for ((i=0;i<=100;i++)); do
# Pure bash micro sleeps (for the example).
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
# Print the bar.
bar "$i" "10"
done
printf '\n'
```
## Get the list of functions in a script
```sh
get_functions() {
# Usage: get_functions
IFS=$'\n' read -d "" -ra functions < <(declare -F)
printf '%s\n' "${functions[@]//declare -f }"
}
```
## Bypass shell aliases
```shell
# alias
ls
# command
# shellcheck disable=SC1001
\ls
```
## Bypass shell functions
```shell
# function
ls
# command
command ls
``` ```
<!-- CHAPTER END --> <!-- CHAPTER END -->

190
manuscript/chapter18.txt Normal file
View File

@@ -0,0 +1,190 @@
# OTHER
## Use `read` as an alternative to the `sleep` command
Surprisingly, `sleep` is an external command and not a `bash` built-in.
**CAVEAT:** Requires `bash` 4+
**Example Function:**
```sh
read_sleep() {
# Usage: sleep 1
# sleep 0.2
read -rst "${1:-1}" -N 999
}
```
**Example Usage:**
```shell
read_sleep 1
read_sleep 0.1
read_sleep 30
```
## Check if a program is in the user's PATH
```shell
# There are 3 ways to do this and either one can be used.
type -p executable_name &>/dev/null
hash executable_name &>/dev/null
command -v executable_name &>/dev/null
# As a test.
if type -p executable_name &>/dev/null; then
# Program is in PATH.
fi
# Inverse.
if ! type -p executable_name &>/dev/null; then
# Program is not in PATH.
fi
# Example (Exit early if program is not installed).
if ! type -p convert &>/dev/null; then
printf '%s\n' "error: convert is not installed, exiting..."
exit 1
fi
```
## Get the current date using `strftime`
Bashs `printf` has a built-in method of getting the date which can be used in place of the `date` command.
**CAVEAT:** Requires `bash` 4+
**Example Function:**
```sh
date() {
# Usage: date "format"
# See: 'man strftime' for format.
printf "%($1)T\\n" "-1"
}
```
**Example Usage:**
```shell
# Using above function.
$ date "%a %d %b - %l:%M %p"
Fri 15 Jun - 10:00 AM
# Using printf directly.
$ printf '%(%a %d %b - %l:%M %p)T\n' "-1"
Fri 15 Jun - 10:00 AM
# Assigning a variable using printf.
$ printf -v date '%(%a %d %b - %l:%M %p)T\n' '-1'
$ printf '%s\n' "$date"
Fri 15 Jun - 10:00 AM
```
## Generate a UUID V4
**Example Function:**
```sh
uuid() {
# Usage: uuid
C="89ab"
for ((N=0;N<16;++N)); do
B="$((RANDOM%256))"
case "$N" in
6) printf '4%x' "$((B%16))" ;;
8) printf '%c%x' "${C:$RANDOM%${#C}:1}" "$((B%16))" ;;
3|5|7|9)
printf '%02x-' "$B"
;;
*)
printf '%02x' "$B"
;;
esac
done
printf '\n'
}
```
**Example Usage:**
```shell
$ uuid
d5b6c731-1310-4c24-9fe3-55d556d44374
```
## Progress bars
This is a simple way of drawing progress bars without needing a for loop
in the function itself.
**Example Function:**
```sh
bar() {
# Usage: bar 1 10
# ^----- Elapsed Percentage (0-100).
# ^-- Total length in chars.
((elapsed=$1*$2/100))
# Create the bar with spaces.
printf -v prog "%${elapsed}s"
printf -v total "%$(($2-elapsed))s"
printf '%s\r' "[${prog// /-}${total}]"
}
```
**Example Usage:**
```shell
for ((i=0;i<=100;i++)); do
# Pure bash micro sleeps (for the example).
(:;:) && (:;:) && (:;:) && (:;:) && (:;:)
# Print the bar.
bar "$i" "10"
done
printf '\n'
```
## Get the list of functions in a script
```sh
get_functions() {
# Usage: get_functions
IFS=$'\n' read -d "" -ra functions < <(declare -F)
printf '%s\n' "${functions[@]//declare -f }"
}
```
## Bypass shell aliases
```shell
# alias
ls
# command
# shellcheck disable=SC1001
\ls
```
## Bypass shell functions
```shell
# function
ls
# command
command ls
```
<!-- CHAPTER END -->