Reputation: 4832
I would like to write a function that takes an array variable name and updates the contents. For example:
ARRAY1=("test 1" "test 2" "test 3")
toUpper ARRAY1
for arg in "${ARRAY1[@]}"; do
echo "arg=$arg"
done
# output
arg=TEST 1
arg=TEST 2
arg=TEST 3
I have a crude attempt at doing this which requires a copy of the input array. Using indirect references, I am able to create a copy of the input variable. The copy of the array is used to get the count of the elements. If there is a better way to do this please let me know.
function toUpper() {
local ARRAY_NAME=$1
local ARRAY_REF="$ARRAY_NAME[@]"
# use an indirect reference to copy the array so we can get the count
declare -a ARRAY=("${!ARRAY_REF}")
local COUNT=${#ARRAY[@]}
for ((i=0; i<$COUNT; i++)); do
local VAL="${ARRAY[$i]}"
VAL=$(echo $VAL | tr [:lower:] [:upper:])
echo "ARRAY[$i]=\"$VAL\""
eval "$ARRAY_NAME[$i]=\"$VAL\""
done
}
ARRAY1=( "test" "test 1" "test 3" )
toUpper ARRAY1
echo
echo "Printing array contents"
for arg in "${ARRAY1[@]}"; do
echo "arg=$arg"
done
Upvotes: 1
Views: 1284
Reputation: 785316
Using BASH 4.3+ you can do
arr=( "test" "test 1" "test 3" )
toUpper() { declare -n tmp="$1"; printf "%s\n" "${tmp[@]^^}"; }
toUpper arr
TEST
TEST 1
TEST 3
Update: To reflect the changes in original array:
toUpper() {
declare -n tmp="$1";
for ((i=0; i<"${#tmp[@]}"; i++)); do
tmp[i]="${tmp[i]^^}"
done;
}
arr=( "test" "test 1" "test 3" )
toUpper arr
printf "%s\n" "${arr[@]}"
TEST
TEST 1
TEST 3
Update2: Here is a way to make it work in older BASH (prior to 4) versions without eval
:
upper() {
len=$2
for ((i=0; i<len; i++)); do
elem="${1}[$i]"
val=$(tr '[:lower:]' '[:upper:]' <<< "${!elem}")
IFS= read -d '' -r "${1}[$i]" < <(printf '%s\0' "$val")
done;
}
arr=( "test" "test 1" "test 3" )
upper arr ${#arr[@]}
printf "%s\n" "${arr[@]}"
TEST
TEST 1
TEST 3
Upvotes: 6
Reputation: 295520
anubhava's answer is ideal for bash 4.3 or newer. To support bash 3, one can use eval
(very cautiously, with strings generated with printf %q
) to replace the use of namevars, and tr
to replace the ${foo^^}
expansion for upper case:
toUpper() {
declare -a indexes
local cmd idx item result
printf -v cmd 'indexes=( "${!%q[@]}" )' "$1"; eval "$cmd"
for idx in "${indexes[@]}"; do
printf -v cmd 'item=${%q[%q]}' "$1" "$idx"; eval "$cmd"
result=$(tr '[:lower:]' '[:upper:]' <<<"$item")
printf -v cmd '%q[%q]=%q' "$1" "$idx" "$result"; eval "$cmd"
done
}
Upvotes: 1