Use #
and ##
to match from the start of a string and return the shortest and
longest possible match, respectively. Alternatively, use %
and %%
for
matching from the end of strings. After expansion, what is returned is the
remaining portions of the string that were unmatched.
To illustrate, the following (result in comment):
var="one.two.three.four"
${var} # one.two.three.four
${var#*.} # two.three.four
${var##*.} # four
${var%.*} # one.two.three
${var%%.*} # one
${var,,pattern} # lowercase all
${var,pattern} # lowercase first letter
${var^^pattern} # uppercase all
${var^pattern} # uppercase first letter
If pattern
is unspecified, all possible characters to convert will be
converted.
When applied to an array (subscripted by [@]
or [*]
, the pattern is applied
to each item. Items are then returned as a list.
An alternate method is to use the @
and an operator:
${var@U} # all uppercase
${var@u} # 1st character uppercase
${var@L} # all lowercase
[ -s <file> ]
[ -r <file> ]
Rather than embed echo
in several places of a script, run:
sh -vx <script>
-v
will cause each command to be echoed before running, and -x
will echo the
output of each command. This can also be accomplished by setting (set -vx
)
after the shebang in the script itself.
Add the -n
flag check syntax without executing the script.
To prevent the user from interrupting a process, add:
trap '' 2
The signal 2
corresponds to user interrupt (CTRL+C
). To undo this and
re-enable interrupts, use:
trap 2
These two invocations can be used to prevent a sensitive section of code from being interrupted.
When constructing functions to use as part of a sequence of pipes, one may require logic that processes standard input.
To iterate over each line of standard input, use:
while read -r line
...
done <<< "$(< /dev/stdin)"
Alternatively, to store all the input in a variable, use:
var=$(< /dev/stdin)
To store multiple inputs from stdin as separate entries of an array, run:
read -r -a var <<< "${@}"
Note: If the values are newline delimited, use mapfile -t arr <<< "${@}"
instead.
To source a script, for example, to define variables and functions, wrap the execution logic (that is not to be executed) as follows:
if [ "$0" = "${BASH_SOURCE[0]}" ]; then
...
fi
Any code inside the if
block will only be executed when the script itself is
directly executed.
for ((i=32;i<127;i++)) do printf "\\$(printf %03o "$i")"; done; printf "\n"
To quickly parallelize a for
loop, use a counter, &
, and wait
to run up to
N
commands at once. Run:
N="$(nproc)"
i=0
for ...; do
<command> &
i=$((i+1))
if [ $((i%N)) -eq 0 ]; then
i=0
wait
fi
done
wait
Either specify the absolute path or use command
:
command <cmd>
To delete a value from a Bash array, use unset
as follows:
unset arr[0]
The above command removes the 0
th element of an array called arr
. Note that
the indices of the array do not change (i.e. the 1
st element is not re-indexed
to the 0
th).
Should resetting indices be necessary, a new array needs to be created. Use:
unset arr[0]
arr=(${arr[@])
arr=(1 2 3 4 5)
echo "${arr[@:2]}"
The above will print from the 2nd element (inclusive) onward.