diff options
author | 2024-06-27 16:15:51 +0100 | |
---|---|---|
committer | 2024-06-28 18:39:01 +0100 | |
commit | 9caeb57e67c48376fbd7d8121ae4d3a9e1888b35 (patch) | |
tree | 20ba2798a3975c7eb3cc50d1bf1b2328f4cc40c0 | |
parent | Add an experimental module for staging new ideas (diff) | |
download | gentoo-functions-9caeb57e67c48376fbd7d8121ae4d3a9e1888b35.tar.gz gentoo-functions-9caeb57e67c48376fbd7d8121ae4d3a9e1888b35.tar.bz2 gentoo-functions-9caeb57e67c48376fbd7d8121ae4d3a9e1888b35.zip |
Add the substr() function
POSIX sh does not support substring expansion so it may come in handy.
The implementation is based on the awk function of the same name.
Signed-off-by: Kerin Millar <kfm@plushkava.net>
-rw-r--r-- | functions.sh | 41 | ||||
-rwxr-xr-x | test-functions | 39 |
2 files changed, 80 insertions, 0 deletions
diff --git a/functions.sh b/functions.sh index 798c6c7..43a21e4 100644 --- a/functions.sh +++ b/functions.sh @@ -439,6 +439,47 @@ srandom() } # +# Takes the first parameter as a string (s), the second parameter as a numerical +# position (m) and, optionally, the third parameter as a numerical length (n). +# It shall then print a <newline> terminated substring of s that is at most, n +# characters in length and which begins at position m, numbering from 1. If n is +# omitted, or if n specifies more characters than are left in the string, the +# length of the substring shall be limited by the length of s. The function +# shall return 0 provided that none of the parameters are invalid. +# +substr() +{ + local i str + + if [ "$#" -lt 2 ]; then + warn "substr: too few arguments (got $#, expected at least 2)" + return 1 + elif ! is_int "$2"; then + _warn_for_args substr "$2" + return 1 + elif [ "$#" -ge 3 ]; then + if ! is_int "$3"; then + _warn_for_args substr "$3" + return 1 + elif [ "$3" -lt 0 ]; then + set -- "$1" "$2" 0 + fi + fi + str=$1 + i=0 + while [ "$(( i += 1 ))" -lt "$2" ]; do + str=${str#?} + done + i=0 + while [ "${#str}" -gt "${3-${#str}}" ]; do + str=${str%?} + done + if [ "${#str}" -gt 0 ]; then + printf '%s\n' "${str}" + fi +} + +# # Trims leading and trailing whitespace from one or more lines. If at least one # parameter is provided, each positional parameter shall be considered as a line # to be processed. Otherwise, the lines to be processed shall be read from the diff --git a/test-functions b/test-functions index 13be61c..736836b 100755 --- a/test-functions +++ b/test-functions @@ -664,6 +664,44 @@ test_trueof_any() { iterate_tests 7 "$@" } +test_substr() { + set -- \ + ge 1 - foobar N/A N/A \ + ge 1 - foobar '' N/A \ + ge 1 - foobar x N/A \ + ge 1 - foobar '' '' \ + ge 1 - foobar x y \ + eq 0 foobar foobar 1 N/A \ + eq 0 foobar foobar -1 N/A \ + eq 0 foobar foobar 1 7 \ + eq 0 foobar foobar -1 7 \ + eq 0 foo foobar 1 3 \ + eq 0 foo foobar -1 3 \ + eq 0 f foobar 1 1 \ + eq 0 f foobar -1 1 \ + eq 0 '' foobar 1 0 \ + eq 0 '' foobar 1 -1 \ + eq 0 '' foobar 0 0 \ + eq 0 '' foobar 0 -1 \ + eq 0 '' foobar -1 0 \ + eq 0 '' foobar -1 -1 \ + eq 0 bar foobar 4 N/A \ + eq 0 bar foobar 4 4 \ + eq 0 b foobar 4 1 \ + eq 0 '' foobar 4 0 \ + eq 0 '' foobar 4 -1 + + callback() { + shift + expected=$1 + shift + test_description="substr $(quote_args "$@")" + str=$(substr "$@") && test "${str}" = "${expected}" + } + + iterate_tests 6 "$@" +} + iterate_tests() { slice_width=$1 shift @@ -738,6 +776,7 @@ test_is_anyof || rc=1 test_is_subset || rc=1 test_trueof_all || rc=1 test_trueof_any || rc=1 +test_substr || rc=1 cleanup_tmpdir |