diff --git a/SC3057.md b/SC3057.md index af8cda1..af512e3 100644 --- a/SC3057.md +++ b/SC3057.md @@ -28,25 +28,112 @@ done printf '%s\n' "${argument-}" ``` -An alternative could be to use a delimiting character instead. For instance, to use texts prefixed with a number, an option is to use a colon as a delimiter and use that in a parameter expansion that removes a pattern form either beginning or ending of variable value: +#### Use `parameter expansion` instead + +An alternative could be to use parameter expansion instead of string indexing. +Either [through a delimiting character](#through-a-delimiting-character), +[through matching undesired parts of a text](#through-matching-undesired-parts-of-the-text), +or [through a "simple" pattern of `length` size](#through-a-simple-pattern). + +##### Through a delimiting character + +For instance, to use texts prefixed with a number, +an option is to use a colon as a delimiter +and use that in a parameter expansion +that removes a pattern form either beginning or ending of variable value. ```sh -#!/bin/sh -exitForReasonX='4:Stopping %s because of X.' -exitForReasonY='6:Stopping because of Y.' -echo "The ''reason y'' has number '${exitForReasonY#*:}' and its message is: '${exitForReasonY%%:*}'." -# A more useful example might be : +#!/usr/bin/env sh +exitForReasonY='6:Stopping because of 8x Y.' +printf "The ''reason y'' has number '%s' and its message is: '%s'." "${exitForReasonY#*:}" "${exitForReasonY%%:*}" +``` + +Or, in a function: + +```sh +#!/usr/bin/env sh +exitForReasonX='44:Stopping %s because of X.' reasonableExit () { state="${1:-}" state="${state:?is required}" ${1+shift} - >&2 printf '%s\n' "${state%%:*}" ${1+"${@?}"} - exit "${state#*:}" + set -- "${state#*:}" ${1+"${@?}"} + >&2 printf "${@?}" + exit "${state%%:*}" } reasonableExit "${exitForReasonX?}" 'something' ``` +##### Through matching undesired parts of the text + +Another way could be to remove what is unwanted by selecting that. + +```sh +#!/usr/bin/env sh +exitForReasonY='6Stopping because of 8x Y.' +yNumber="${exitForReasonY%%[![:digit:]]*}" +yText="${exitForReasonY#${exitForReasonY%%[![:digit:]]*}}" +# or : yText="${exitForReasonY#${yNumber?}" +printf "The ''reason y'' has number '%s' and its message is: '%s'.\n" "${yNumber?}" "${yText?}" +``` + +Or, in a function: +```sh +#!/usr/bin/env sh +exitForReasonX='44Stopping %s because of X.' +reasonableExit () +{ + text="${1:-}" + text="${text:?is required}" + ${1+shift} + state="${text%%[![:digit:]]*}" + set -- "${text#"${state?}"}" ${1+"${@?}"} + >&2 printf "${@?}" + exit "${state?}" +} +reasonableExit "${exitForReasonX?}" 'something' +``` + +##### Through a "simple" pattern + +Remove the smallest _prefix_ from a text where prefix matches a pattern that matches any character as many times as the sum of start and length. +Remove the smallest _suffix that matches that previous text from the original text. +Remove the smallest _prefix_ that matches any character as many times as the start index. + +This could also be the other way around, selecting an offset from the end of a text. + +```sh +#!/usr/bin/env sh + +part="zyxwvutsrqponmlkjihgfedcba" +#echo "${part:5:3}" +part="${part%${part#????????}}" +part="${part#?????}" +printf '%s\n' "${part?}" +``` +Code "walkthrough" + +```sh +#!/usr/bin/env sh + +part="zyxwvutsrqponmlkjihgfedcba" +#echo "${part:5:3}" + +part="${part%${part#????????}}" +## Removed smallest prefix from text where prefix matches pattern ???????? +## in this case : "rqponmlkjihgfedcba" +## "${part%${part#????????}}" = "${part%"rqponmlkjihgfedcba"}" = "zyxwvuts" +## Removed smallest suffix from part of text where suffix matches pattern ${part#????????} (i.e. "rqponmlkjihgfedcba") + +part="${part#?????}" +## Removed smallest prefix from text where prefix matches ????? (i.e. "zyxwv") + +printf '%s\n' "${part?}" +``` + + + ### Rationale: String indexing is a bash and ksh extension, and does not work in `dash` or POSIX `sh`.