避免在复制字符串数组时对其进行 bash 拆分



为了保持脚本简单,我使用字符串变量作为变量名称来恢复其他变量(在本例中为数组(:

#!/usr/bin/env bash
ANDROID_BUILD_OPTIONS=("armeabi-v7a" "arm64-v8a")
ANDROID_BUILD_DESCRIPTIONS=("Regular ARM 32-bit" "Regular ARM 64-bit")
ANDROID_BUILD_OPTIONS_COUNT=2
IOS_BUILD_OPTIONS=("base")
IOS_BUILD_DESCRIPTIONS=("Basic xcode target (ignored on non-MacOS build)")
IOS_BUILD_OPTIONS_COUNT=1
# Initial print of the arrays
echo "- ANDROID_BUILD_DESCRIPTIONS -"
i=0
while [ $i -lt ${ANDROID_BUILD_OPTIONS_COUNT} ]; do
echo "[$i] Name: ${ANDROID_BUILD_OPTIONS[i]}, description: ${ANDROID_BUILD_DESCRIPTIONS[i]}"
i=$((i + 1))
done
echo "- IOS_BUILD_DESCRIPTIONS -"
i=0
while [ $i -lt ${IOS_BUILD_OPTIONS_COUNT} ]; do
echo "[$i] Name: ${IOS_BUILD_OPTIONS[i]}, description: ${IOS_BUILD_DESCRIPTIONS[i]}"
i=$((i + 1))
done
echo
for TARGET in ANDROID IOS; do
varname="${TARGET}_BUILD_OPTIONS[@]"
TARGET_BUILD_OPTIONS=${!varname}
varname="${TARGET}_BUILD_DESCRIPTIONS[@]"
TARGET_BUILD_DESCRIPTIONS=${!varname}
varname="${TARGET}_BUILD_OPTIONS_COUNT"
TARGET_BUILD_OPTIONS_COUNT=${!varname}
echo "- TARGET_BUILD_DESCRIPTIONS (${TARGET}) -"
i=0
while [ $i -lt ${TARGET_BUILD_OPTIONS_COUNT} ]; do
echo "[$i] Name: ${TARGET_BUILD_OPTIONS[i]}, description: ${TARGET_BUILD_DESCRIPTIONS[i]}"
i=$((i + 1))
done
done

上面的脚本生成以下输出:

- ANDROID_BUILD_DESCRIPTIONS -
[0] Name: armeabi-v7a, description: Regular ARM 32-bit
[1] Name: arm64-v8a, description: Regular ARM 64-bit
- IOS_BUILD_DESCRIPTIONS -
[0] Name: base, description: Basic xcode target (ignored on non-MacOS build)
- TARGET_BUILD_DESCRIPTIONS (ANDROID) -
[0] Name: armeabi-v7a arm64-v8a, description: Regular ARM 32-bit Regular ARM 64-bit
[1] Name: , description: 
- TARGET_BUILD_DESCRIPTIONS (IOS) -
[0] Name: base, description: Basic xcode target (ignored on non-MacOS build)

正如您在输出中看到的,原始数组已正确组装,其内容已正确显示。但是在变量名替换和数组复制之后,内容被组装成一个大字符串......这完全破坏了数组的内容,因为在这种情况下,它包含 IFS 分隔的值(默认情况下为 ' '/空格(。

然后我尝试了另一种方法,我不明白为什么这种方法不起作用。我基本上将TARGET_BUILD_OPTIONS创建为一个全新的数组,然后一次一个元素地迭代ANDROID/IOS_BUILD_OPTIONS的内容,并复制它。以下是更新的代码:

TARGET_BUILD_OPTIONS=()
TARGET_BUILD_DESCRIPTIONS=()
if [ "${TARGET}" = "ANDROID" ]; then
COUNTER=0
while [ "${COUNTER}" -lt "${ANDROID_BUILD_OPTIONS_COUNT}" ]; do
TARGET_BUILD_OPTIONS+=(${ANDROID_BUILD_OPTIONS[COUNTER]})
TARGET_BUILD_DESCRIPTIONS+=(${ANDROID_BUILD_DESCRIPTIONS[COUNTER]})
COUNTER=$((COUNTER + 1))
done
else
COUNTER=0
while [ "${COUNTER}" -lt "${IOS_BUILD_OPTIONS_COUNT}" ]; do
TARGET_BUILD_OPTIONS+=(${IOS_BUILD_OPTIONS[COUNTER]})
TARGET_BUILD_DESCRIPTIONS+=(${IOS_BUILD_DESCRIPTIONS[COUNTER]})
COUNTER=$((COUNTER + 1))
done
fi

令我惊讶的是...这也行不通。它似乎遍历字符串,一次一个单词:

- ANDROID_BUILD_DESCRIPTIONS -
[0] Name: armeabi-v7a, description: Regular ARM 32-bit
[1] Name: arm64-v8a, description: Regular ARM 64-bit
- IOS_BUILD_DESCRIPTIONS -
[0] Name: base, description: Basic xcode target (ignored on non-MacOS build)
- TARGET_BUILD_DESCRIPTIONS (ANDROID) -
[0] Name: armeabi-v7a, description: Regular
[1] Name: arm64-v8a, description: ARM
- TARGET_BUILD_DESCRIPTIONS (IOS) -
[0] Name: base, description: Basic

非常令人惊讶的是,它是之前用于打印的同一段代码。以下是彼此相邻的两段代码:

# Correctly prints the complete strings one array element after the other
COUNTER=0
while [ $COUNTER -lt ${ANDROID_BUILD_OPTIONS_COUNT} ]; do
echo "$COUNTER: ${ANDROID_BUILD_DESCRIPTIONS[COUNTER]}"
echo "$i: ${ANDROID_BUILD_OPTIONS[i]}, ${ANDROID_BUILD_DESCRIPTIONS[i]}"
COUNTER=$((COUNTER + 1))
done
# Copies the element one word by one word, using ' '/space as a separator?
COUNTER=0
while [ "${COUNTER}" -lt "${ANDROID_BUILD_OPTIONS_COUNT}" ]; do
TARGET_BUILD_OPTIONS+=(${ANDROID_BUILD_OPTIONS[COUNTER]})
TARGET_BUILD_DESCRIPTIONS+=(${ANDROID_BUILD_DESCRIPTIONS[COUNTER]})
COUNTER=$((COUNTER + 1))
done

有谁知道引擎盖下发生了什么?我怎样才能实现我正在寻找的行为?

提前谢谢。

问题是您已将整个数组内容作为单个字符串扩展到变量TARGET_BUILD_OPTIONS而不是数组。 即,TARGET_BUILD_OPTIONS="${!varname}会将内容视为单个字符串。

varname="${TARGET}_BUILD_OPTIONS[@]"这句话之后,varname就变成了ANDROID_BUILD_OPTIONS[@]。因此,当您提供TARGET_BUILD_OPTIONS="${!varname}"时,它将被设置为TARGET_BUILD_OPTIONS=armeabi-v7a arm64-v8a

另一方面,当你给出TARGET_BUILD_OPTIONS=("${!variable}")时,它确实会被视为一个数组TARGET_BUILD_OPTIONS=(armeabi-v7a arm64-v8a)

因此,如果将其扩展为数组(设置为TARGET_BUILD_OPTIONS=("${!varname}")(,则脚本将起作用。

for TARGET in ANDROID IOS; do
varname="${TARGET}_BUILD_OPTIONS[@]"
TARGET_BUILD_OPTIONS=("${!varname}")
varname="${TARGET}_BUILD_DESCRIPTIONS[@]"
TARGET_BUILD_DESCRIPTIONS=("${!varname}")
varname="${TARGET}_BUILD_OPTIONS_COUNT"
TARGET_BUILD_OPTIONS_COUNT=${!varname}
echo "- TARGET_BUILD_DESCRIPTIONS (${TARGET}) -"
i=0
while [ $i -lt ${TARGET_BUILD_OPTIONS_COUNT} ]; do
echo "[$i] Name: ${TARGET_BUILD_OPTIONS[i]}, description: ${TARGET_BUILD_DESCRIPTIONS[i]}"
i=$((i + 1))
done
done

第二种方法(创建一个空数组并将项目逐个推送到其中(有效,但IFS需要先取消设置,尽管我不完全明白为什么。

IFS=
if [ "${TARGET}" = "ANDROID" ]; then
COUNTER=0
while [ "${COUNTER}" -lt "${ANDROID_BUILD_OPTIONS_COUNT}" ]; do
TARGET_BUILD_OPTIONS+=(${ANDROID_BUILD_OPTIONS[COUNTER]})
TARGET_BUILD_DESCRIPTIONS+=(${ANDROID_BUILD_DESCRIPTIONS[COUNTER]})
COUNTER=$((COUNTER + 1))
done
else
COUNTER=0
while [ "${COUNTER}" -lt "${IOS_BUILD_OPTIONS_COUNT}" ]; do
TARGET_BUILD_OPTIONS+=(${IOS_BUILD_OPTIONS[COUNTER]})
TARGET_BUILD_DESCRIPTIONS+=(${IOS_BUILD_DESCRIPTIONS[COUNTER]})
COUNTER=$((COUNTER + 1))
done
fi
IFS="${OLD_IFS}"

使用数组中的正确值,也可以丢弃_COUNT变量,因为${#ARRAY_NAME[@]}将返回其大小。

最新更新