mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-10-03 19:29:44 +08:00
Added examples of parameter expansion techniques to mimic string indexing
103
SC3057.md
103
SC3057.md
@@ -28,25 +28,112 @@ done
|
|||||||
printf '%s\n' "${argument-}"
|
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
|
```sh
|
||||||
#!/bin/sh
|
#!/usr/bin/env sh
|
||||||
exitForReasonX='4:Stopping %s because of X.'
|
exitForReasonY='6:Stopping because of 8x Y.'
|
||||||
exitForReasonY='6:Stopping because of Y.'
|
printf "The ''reason y'' has number '%s' and its message is: '%s'." "${exitForReasonY#*:}" "${exitForReasonY%%:*}"
|
||||||
echo "The ''reason y'' has number '${exitForReasonY#*:}' and its message is: '${exitForReasonY%%:*}'."
|
```
|
||||||
# A more useful example might be :
|
|
||||||
|
Or, in a function:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
exitForReasonX='44:Stopping %s because of X.'
|
||||||
reasonableExit ()
|
reasonableExit ()
|
||||||
{
|
{
|
||||||
state="${1:-}"
|
state="${1:-}"
|
||||||
state="${state:?is required}"
|
state="${state:?is required}"
|
||||||
${1+shift}
|
${1+shift}
|
||||||
>&2 printf '%s\n' "${state%%:*}" ${1+"${@?}"}
|
set -- "${state#*:}" ${1+"${@?}"}
|
||||||
exit "${state#*:}"
|
>&2 printf "${@?}"
|
||||||
|
exit "${state%%:*}"
|
||||||
}
|
}
|
||||||
reasonableExit "${exitForReasonX?}" 'something'
|
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:
|
### Rationale:
|
||||||
|
|
||||||
String indexing is a bash and ksh extension, and does not work in `dash` or POSIX `sh`.
|
String indexing is a bash and ksh extension, and does not work in `dash` or POSIX `sh`.
|
||||||
|
Reference in New Issue
Block a user