From 4d382f82b38e508dc7734fb5d7ac41af4fa6ada6 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Tue, 17 Aug 2021 13:39:25 -0700 Subject: [PATCH] Created SC2302 (markdown) --- SC2302.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 SC2302.md diff --git a/SC2302.md b/SC2302.md new file mode 100644 index 0000000..650814e --- /dev/null +++ b/SC2302.md @@ -0,0 +1,67 @@ +## This loops over values. To loop over keys, use "${!array[@]}". + +Plus companion warning [[SC2303]]: `i is an array value, not a key. Use directly or loop over keys instead.` + +### Problematic code: + +```sh +array=(foo bar) +for i in "${array[@]}" +do + echo "Value is ${array[$i]}" +done +``` + +### Correct code: + +Either loop over values + +```sh +for i in "${array[@]}" +do + echo "Value is $i" +done +``` + +or loop over keys: + +```sh +for i in "${!array[@]}" +do + echo "Key is $i" + echo "Value is ${array[$i]}" +done +``` + +### Rationale: + +ShellCheck found a `for` loop over array *values*, where the variable is used as an array *key*. + +In the problematic example, the loop will print `Value is foo` twice. On the second iteration, `i=bar`, and `bar` is unset and considered zero, so `${array[$i]}` becomes `${array[bar]}` becomes `${array[0]}` becomes `foo`. + +If you don't care about the key, simply loop over array values and use `$i` to refer to the array value, like in the first correct example. + +If you do want the key, loop over array keys with `"${!array[@]}"`, use `$i` to refer to the array key, and `${array[$i]}` to refer to the array value. + +### Exceptions: + +If you do want to use values from the arrays as keys in the same array, you can [[ignore]] these messages with a directive: + +```sh +declare -A fatherOf=( + ["Eric Bloodaxe"]="Harald Fairhair" + ["Harald Fairhair"]="Halfdan the Black" + ["Halfdan the Black"]="Gudrød the Hunter" + ["Gudrød the Hunter"]="Halfdan the Mild" +) + +# shellcheck disable=SC2302,SC23203 +for i in "${fatherOf[@]}" +do + echo "${fatherOf[$i]:-(missing)} begat $i" +done +``` + +### Related resources: + +* Help by adding links to BashFAQ, StackOverflow, man pages, POSIX, etc! \ No newline at end of file