Pure Bash Bible Strings
Edit me
Pure Bash Bible - Strings
=====
Trim leading and trailing white-space from string
This is an alternative to sed
, awk
, perl
and other tools. The function below works by finding all leading and trailing white-space and removing it from the start and end of the string. The :
built-in is used in place of a temporary variable.
Function
trim_string() {
# Usage: trim_string " example string "
: "${1#"${1%%[![:space:]]*}"}"
# [![:space:]]* -> string from the first non-space charactor to the end
# "${1%%[![:space:]]*}" -> greedly remove above string from the end, remaining is space prefix
#
# string=" matrix is nice "
#
# $ string1="${string%%[![:space:]]*}"
#
# $ echo "${#string1}"
# 8
#
# "${1#"${1%%[![:space:]]*}"}" -> remove space prefix from the start
#
# $ string2="${string#${string1}}"
#
# $ echo "${string2}"
# matrix is nice
#
# $ echo "${#string2}"
# 20
#
: "${_%"${_##*[![:space:]]}"}"
# *[![:space:]] -> string from start to the a non-space charactor, 'matrix is nice'
# ${_##*[![:space:]]} -> greedly remove above string from the start, remove 'matrix is nice' from the start, remaining is space suffix
#
# $ string3="${string2##*[![:space:]]}"
#
# $ echo "${#string3}"
# 6
#
# "${_%"${_##*[![:space:]]}"}" -> remove space suffix from the end
#
# $ string4="${string2%${string3}}"
#
# $ echo "${#string4}"
# 14
#
# $ echo "${string4}"
# matrix is nice
printf '%s\n' "$_"
}
Example
$ trim_string " matrix is nice "
matrix is nice
Trim all white-space from string and truncate spaces
This is an alternative to sed
, awk
, perl
and other tools. The function below works by abusing word splitting to create a new string without leading/trailing white-space and with truncated spaces.
Function
trim_all() {
# Usage: trim_all " example string "
set -f
# -f noglob
# Disable [pathname expansion (globbing)](https://wiki.bash-hackers.org/syntax/expansion/globs)
set -- $*
# -- If no arguments follow, the positional parameters are unset. With arguments, the positional parameters are set, even if the strings begin with a - (dash) like an option.
printf '%s\n' "$*"
set +f
}
Example
$ trim_all " matrix is nice "
matrix is nice
Use regex on a string
The result of bash
’s regex matching can be used to replace sed
for a large number of use-cases.
Function
regex() {
# Usage: regex "string" "regex"
[[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}"
}
Example
# Trim leading white-space.
$ regex ' hello' '^\s*(.*)'
hello
# Validate a hex color.
$ regex "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
#FFFFFF
# Validate a hex color (invalid).
$ regex "red" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
# no output (invalid)
$ cat color_verify.sh
#!/bin/bash
$ is_hex_color() {
if [[ $1 =~ ^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$ ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
else
printf '%s\n' "error: $1 is an invalid color."
return 1
fi
}
read -r color
is_hex_color "$color" || color="#FFFFFF"
$ echo "#95968d" | ./color_verify.sh
#95968d
$ echo "red" | ./color_verify.sh
error: red is an invalid color.
Split a string on a delimiter
This is an alternative to cut
, awk
and other tools.
Function
split() {
# Usage: split "string" "delimiter"
IFS=$'\n' read -d "" -ra arr <<< "${1//$2/$'\n'}"
# "${1//$2/$'\n'}" -> within $1, replace all $2 with $'\n'
# read
# -d delim
# The first character of delim is used to terminate the input line, rather than newline.
# -r Backslash does not act as an escape character. The backslash is considered to be part of the line. In particular, a backslash-newline pair may not be used as a line continuation.
# -a aname
# The words are assigned to sequential indices of the array variable aname, starting at 0. aname is unset before any new values are assigned. Other name arguments are ignored.
printf '%s\n' "${arr[@]}"
}
Example
$ split "apple,oranges,pears,grapes" ","
apple
oranges
pears
grapes
$ split "1, 2, 3, 4, 5" ", "
1
2
3
4
5
lowercase / uppercase change or revert
Functions
lower() {
# Usage: lower "string"
printf '%s\n' "${1,,}"
}
upper() {
# Usage: upper "string"
printf '%s\n' "${1^^}"
}
reverse_case() {
# Usage: reverse_case "string"
printf '%s\n' "${1~~}"
}
Trim quotes from a string
Function
trim_quotes() {
# Usage: trim_quotes "string"
: "${1//\'}"
printf '%s\n' "${_//\"}"
}
Example
$ var="'Hello', \"World\""
$ trim_quotese "${var}"
Hello, World
Strip all instances of pattern from string
Function
strip_all() {
# Usage: strip_all "string" "pattern"
printf '%s\n' "${1//$2}"
}
Example
$ strip_all "The Quick Brown Fox" "[[:space:]]"
TheQuickBrownFox
$ strip_all "The Quick Brown Fox" "[aeiou]"
Th Qck Brwn Fx
Percent-encode / decode a string
Function
urlencode() {
# Usage: urlencode "string"
local LC_ALL=C
for (( i = 0; i < ${#1}; i++ )); do
: "${1:i:1}"
# slice the `i`th character
case "$_" in
[a-zA-Z0-9.~_-])
printf '%s' "$_"
;;
*)
printf '%%%02X' "'$_"
# if the leading character is a single or double quote, the value is the ASCII value of the following character.
;;
esac
done
printf '\n'
}
urldecode() {
# Usage: urldecode "string"
: "${1//+/ }"
# remove '+'
printf '%b\n' "${_//%/\\x}"
# replace '%' to '\x'
# %b causes printf to expand backslash escape sequences in the corresponding argument (except that \c terminates output, backslashes in \', \", and \? are not removed, and octal escapes beginning with \0 may contain up to four digits).
}
Example
$ urlencode "https://github.com/dylanaraps/pure-bash-bible"
https%3A%2F%2Fgithub.com%2Fdylanaraps%2Fpure-bash-bible
$ urldecode "https%3A%2F%2Fgithub.com%2Fdylanaraps%2Fpure-bash-bible"
https://github.com/dylanaraps/pure-bash-bible
Check if string contains / starts / ends with a sub-string
Function
## Contains
if [[ $var == *sub_string* ]]; then
printf '%s\n' "sub_string is in var."
fi
# Inverse (substring not in string).
if [[ $var != *sub_string* ]]; then
printf '%s\n' "sub_string is not in var."
fi
# This works for arrays too!
if [[ ${arr[*]} == *sub_string* ]]; then
printf '%s\n' "sub_string is in array."
fi
## Starts
if [[ $var == sub_string* ]]; then
printf '%s\n' "var starts with sub_string."
fi
# Inverse (var does not start with sub_string).
if [[ $var != sub_string* ]]; then
printf '%s\n' "var does not start with sub_string."
fi
## Ends
if [[ $var == *sub_string ]]; then
printf '%s\n' "var ends with sub_string."
fi
# Inverse (var does not end with sub_string).
if [[ $var != *sub_string ]]; then
printf '%s\n' "var does not end with sub_string."
fi