title | tags | keywords | last_updated | summary | sidebar | permalink | folder | |
---|---|---|---|---|---|---|---|---|
Pure Bash Bible - Strings |
|
bash, strings |
June 9, 2020 |
Pure Bash Bible Strings |
mydoc_sidebar |
bash_pure_bible_strings.html |
bash |
=====
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.
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' "$_"
}
$ trim_string " matrix is nice "
matrix is nice
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.
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
}
$ trim_all " matrix is nice "
matrix is nice
The result of bash
's regex matching can be used to replace sed
for a large number of use-cases.
regex() {
# Usage: regex "string" "regex"
[[ $1 =~ $2 ]] && printf '%s\n' "${BASH_REMATCH[1]}"
}
# 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.
This is an alternative to cut
, awk
and other tools.
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[@]}"
}
$ split "apple,oranges,pears,grapes" ","
apple
oranges
pears
grapes
$ split "1, 2, 3, 4, 5" ", "
1
2
3
4
5
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() {
# Usage: trim_quotes "string"
: "${1//\'}"
printf '%s\n' "${_//\"}"
}
$ var="'Hello', \"World\""
$ trim_quotese "${var}"
Hello, World
strip_all() {
# Usage: strip_all "string" "pattern"
printf '%s\n' "${1//$2}"
}
$ strip_all "The Quick Brown Fox" "[[:space:]]"
TheQuickBrownFox
$ strip_all "The Quick Brown Fox" "[aeiou]"
Th Qck Brwn Fx
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).
}
$ 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
## 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
{% include links.html %}