From a0e64db1616022d86c729dca762321a69032b310 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Thu, 19 Nov 2020 13:26:41 -0800 Subject: [PATCH] Updated SC2124 (markdown) --- SC2124.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/SC2124.md b/SC2124.md index 76534cb..f24099a 100644 --- a/SC2124.md +++ b/SC2124.md @@ -1,13 +1,9 @@ ## Assigning an array to a string! Assign as array, or use * instead of @ to concatenate. -### Danger! - -> Changing this parameter can be dangerous. Its behavior is influenced by the value of `IFS`. In certain situations (like feeding strings into commands) this can result in unexpected results from a seemingly aesthetic-only change. -[[More info]](https://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables) - ### Problematic code: ```sh +# Want to store multiple elements in var var=$@ for i in $var; do ..; done ``` @@ -16,6 +12,7 @@ or ```sh set -- Hello World +# Want to concatenate multiple elements into a single string msg=$@ echo "You said $msg" ``` @@ -23,14 +20,22 @@ echo "You said $msg" ### Correct code: ```sh +# Bash: use an array variable var=( "$@" ) for i in "${var[@]}"; do ..; done + +# POSIX sh: without array support, one possible workaround +# is to store elements concatenated with a delimiter (here linefeed/newline) +var=$(printf '%s\n' "$@") +printf '%s\n' "$var" | while IFS='' read -r line; do ..; done ``` or ```sh +#!/bin/sh set -- Hello World +# Explicitly concatenates all the array elements into a single string msg=$* echo "You said $msg" ``` @@ -41,7 +46,9 @@ Arrays and `$@` can contain multiple elements. Simple variables contain only one Since doing this usually indicates a bug, ShellCheck warns and asks you to be explicit about what you want. -If you want to assign N elements as N elements, use an array, e.g. `myArray=( "$@" )`. +If you want to assign N elements as N elements in Bash or Ksh, use an array, e.g. `myArray=( "$@" )`. + +Dash and POSIX sh do not support arrays. In this case, either concatenate the values with some delimiter that you can split on later (the example uses linefeeds and splits them back up with a `while read` loop), or keep the values as positional parameters without putting them in an array. If you want to assign N elements as 1 element by concatenating them, use `*` instead of `@`, e.g. `myVar=${myArray[*]}` (this separates elements with the first character of `IFS`, usually space).