Conditional Expression
Note: EXPR && echo true
- on returningtrue
expression is true, otherwise false.
String
Expression |
Description |
[ "$VAR" ] |
String not empty |
[ -z "$VAR" ] or [ ! "$VAR" ] |
String is empty |
[ "$VAR1" = "$VAR2" ] |
Equal string - case-sensitive |
[ "${VAR1,,}" = "${VAR2,,}" ] |
Equal string - case-insensitive |
[ "$VAR1" != "$VAR2" ] |
Not equal string |
[[ "$VAR" =~ "REGEX" ]] |
String matches REGEX |
File
Expression |
Description |
[ -e "$VAR" ] |
File/directory exists |
[ -d "$VAR" ] |
Directory exists |
[ -f "$VAR" ] |
Regular file exists |
[ -s "$VAR" ] |
Regular file exists and not empty |
[ -r "$VAR" ] |
Regular file exists with read permission |
[ -w "$VAR" ] |
Regular file exists with write permission |
[ -x "$VAR" ] |
Regular file exists with exec permission |
Elvis Operator (Ternary)
[REF]
Expression |
Description |
$(( $ORG == 1 ? ${VAL1} : ${VAL2} )) |
inline expression & variable assignment |
$( [ $ORG == "1" ] && echo ${VAL1} || echo ${VAL2} ) |
inline expression & variable assignment |
[ $ORG == "1" ] && VAR="1" || VAR="2" |
only variable assignment |
${VAR:-DEFAULT} |
if VAR is unset or null, DEFAULT is returned |
${VAR:=DEFAULT} |
if VAR is unset or null, DEFAULT is returned and set to VAR itself |
String Operation
Shell Parameter Expansion
Expression |
Description |
${VAR:-DEFAULT} |
If VAR is unset or null, DEFAULT is returned |
${VAR:=DEFAULT} |
If VAR is unset or null, DEFAULT is returned and set to VAR itself |
${VAR:IDX[:LEN]} |
VAR.substr(IDX [,LEN]) |
${VAR,,} |
VAR.toLowercase |
${VAR^^} |
VAR.toUppercase |
${VAR/PAT/STR} |
VAR.replaceFirst(PAT, STR) |
${VAR//PAT/STR} |
VAR.replaceAll(PAT, STR) |
${!VAR} |
consider it as ${${VAR}} |
Split by Delimiter
- Set
IFS
variable to delimiter
read -ra ARRAY <<< STRING
-r
- Backslash does not act as an escape character
-a ARRAY
- The words, separated by IFS
, are assigned to the sequential index of array ARRAY
beginning at zero.
- Access
- By Index -
${ARRAY[0]}
, and so on
- Iteration -
for i in "${ARRAY[@]}"; do ...
1
2
3
4
5
6
7
8
9
10
| if [[ "${SCHEMA}" =~ "|" ]]; then
IFS="|"
read -ra PARTS <<< "${SCHEMA}"
SCHEMA_PARAM="schemas=${PARTS[0]} remap_schema=${PARTS[1]}"
else
SCHEMA_PARAM="schemas=${SCHEMA}"
if [[ "${SCHEMA}" =~ ":" ]]; then
SCHEMA_PARAM="remap_schema=${SCHEMA}"
fi
fi
|
Loop
for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| ## Iterate over CMD output using $()
for i in $(seq 1 1 10); do
echo "i = $i"
done
## Iterate on words: 'Hi!', 'Visit', 'https://devocative.org', and '!'
STR="Hi! Visit https://devocative.org !"
for w in ${STR}; do
echo "w = $w"
done
## Iterate over lines
LINES=$(cat << 'EOF' # EOF must be enclosed in single quote
export LS_OPTIONS='--color=auto'
eval "`dircolors`"
alias ll='ls $LS_OPTIONS -l'
EOF
) # closed parenthesis must be in the next line
IFS=$'\n'
for l in ${LINES}; do
echo "LINE = $l"
done
## Iterate over files
for f in /usr/lib*; do
echo "f = $f"
done
## Iterate over input parameters
for var in "${@}"; do
EXP="${var//[\/:]/_}.tar"
echo "Exporting: ${var} to ${EXP}"
docker save ${var} -o ${EXP}
done
|
Function
- Good [Ref]
- Note:
function
keyword not valid for POSIX sh. For bash
is also optional.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| # check required param
function rq() {
VAR="$1"
MSG="$2"
if [ -z "$VAR" ]; then
echo "ERROR: ${MSG}"
exit 1
fi
}
function func1() {
rq "$1" "func1 *[PARAM1] *PARAM2 PARAM3"
rq "$2" "func1 *PARAM1 *[PARAM2] PARAM3"
PARAM1="$1"
PARAM2="$2"
PARAM3="$3"
# ...
}
func1 "V1" "V2"
#
# function with return value
#
function add() {
rq "$1" "add *[PARAM1] *PARAM2"
rq "$2" "add *PARAM1 *[PARAM2]"
PARAM1="$1"
PARAM2="$2"
echo $((PARAM1 + PARAM2)) # No need to use $ for variables inside '(())'!
}
echo "3 + 6 = $(add "3" "6")"
|
Samples
Inline Code Block in Background (*)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| {
for i in $(seq 1 1 5); do
echo "block = $i"
sleep 1
done
} &
for i in $(seq 1 1 5); do
echo "main = $i"
sleep 2
done
##
## example from following REF! Note using 'wait' command!
{
echo "sleeping for 5 seconds"
sleep 5
echo "woke up"
} &
echo "waiting"
wait
echo "proceed"
|
[REF]
Assert Env Var
- For
bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| E2=b
ENV_VARS="
E1
E2
E3
"
function assertEnvVars() {
VARS="$1"
for VAR in ${VARS}; do # ITERATE OVER WORDS IN STRING
echo "${VAR}"
if [[ ! "${!VAR}" ]]; then # USING ${!} STRING EXPANSION
echo "Var Not Defined: ${VAR}"
fi
done
}
assertEnvVars "${ENV_VARS}" # DOUBLE-QUOTE REQUIRED
|
- For POSIX
sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| E2=b
ENV_VARS="
E1
E2
E3
"
assertEnvVars() { # No 'function' Keyword!
VARS="$1"
for VAR in ${VARS}; do
echo "${VAR}"
eval VAR_VAL="\$${VAR}" # USE 'eval' instead of '${!}'
if [ ! "${VAR_VAL}" ]; then # No '[[]]' Support!
echo "Var Not Defined: ${VAR}"
fi
done
}
assertEnvVars "${ENV_VARS}" # DOUBLE-QUOTE REQUIRED
|
Command with Proxy
A simple script to set http_proxy
env variable in current shell and then executes passed parameters as commands.
Note: replace HOST
and PORT
with your configuration.
1
2
3
4
5
| #! /bin/bash
export http_proxy="http://HOST:PORT"
eval "$@"
|
Dynamic Music Player
- In XFCE keyboard layout, for example set
ctrl + alt + p
to call following script with pop
(play or pause) parameter.
- The player can be
parole
or smplayer
or anything you want.
- Based on priority and running processes, the script decides to send action to selected player.
Upload to a Docker Registry
My tmux
Usage: mytmux.sh CMD...
- For a multi-word command, surround it with single or double quote
- Example:
mytmux.sh 'tail -f file1' 'tail -f file2'
Pars Parametric Text File
[REF]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| # Create a simple text file
# > means create, >> means create/append
# it should be double <<
# EOF means parametric string, while 'EOF' means pure string
# CR should be after first EOF and before second one
cat > myfile.txt << 'EOF'
Hello "${MSG}"!
'${MSG}' has "$(printf '${MSG}' | wc -m)" chars :-)
EOF
MSG="World"
printf "*** Using 'eval & cat':\n"
eval "cat <<EOF
$(<myfile.txt)
EOF" | cat
printf "\n*** Using 'eval & echo':\n"
eval "echo \"$(<myfile.txt)\"" | cat
printf "\n*** Using 'envsubst':\n"
export MSG
envsubst < myfile.txt | cat
rm -f myfile.txt
|
Note: | cat
in all above is just for simulation of another action on the processed file, so it is rudimentary.
Output is
1
2
3
4
5
6
7
8
9
10
11
| *** Using 'eval & cat':
Hello "World"!
'World' has "6" chars :-)
*** Using 'eval & echo':
Hello World!
'World' has 6 chars :-)
*** Using 'envsubst':
Hello "World"!
'World' has "$(printf 'World' | wc -m)" chars :-)
|
Iterate over JSON Array
[REF]
1
2
3
4
5
6
7
8
9
| sample='[{"name":"foo"},{"name":"bar"}]'
for obj in $(echo "${sample}" | jq -r '.[] | @base64'); do
_jq() {
echo ${obj} | base64 --decode | jq -r ${1}
}
echo $(_jq '.name')
done
|
LVM Partition Smart Expand
Setting the partition name, following script find a block device and extend the associated logical volume.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| P_EXTEND="/var"
if [ "${P_EXTEND}" ]; then
echo "Extending Partition: ${P_EXTEND}"
MAP="$(df --output=source ${P_EXTEND} | sed 1d)"
VG="$(lvs -o vg_name,lv_path,lv_dmpath --noheadings | grep "${MAP}" | awk '{print $1}')"
LV="$(lvs -o vg_name,lv_path,lv_dmpath --noheadings | grep "${MAP}" | awk '{print $2}')"
echo "VG = ${VG}, LV = ${LV}, MAP = ${MAP}"
B_DEV="$(pvs -a --noheadings | grep -v ${VG} | awk '{print $1}')"
echo "BLOCK_DEV = ${B_DEV}"
if [ "${B_DEV}" ]; then
vgextend ${VG} ${B_DEV}
lvextend -r -l +100%FREE ${LV}
fi
fi
|
Git/Maven Create Next Snapshot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| #!/bin/bash
if [ ! "$1" ]; then
echo "Pass next version: $0 VERSION"
exit 1
fi
if [[ "$1" =~ -SNAPSHOT$ ]]; then
NEW_VERSION="$1"
else
NEW_VERSION="$1-SNAPSHOT"
fi
echo "Next snapshot version: $NEW_VERSION"
mvn versions:set -DnewVersion="${NEW_VERSION}" -DgenerateBackupPoms=false
git status --porcelain | awk 'match($2, "pom.xml"){print $2}' | xargs git add
git commit -m "Create Next Snapshot: ${NEW_VERSION}"
|