我正在研究一个 bash 函数来帮助我编译包:
make_package() {
local PACKAGE_NAME=$1
local PACKAGE_VERSION=$2
local PACKAGE_INSTALL_DIR=$3
local PACKAGE_CONFIGURE_PARAMETERS=$4
echo "Make ${PACKAGE_NAME}-${PACKAGE_VERSION}"
local BUILD_DIRECTORY=build/${PACKAGE_NAME}-${PACKAGE_VERSION}_build
if [ -d ${BUILD_DIRECTORY} ]; then
rm -rf ${BUILD_DIRECTORY}/*
else
mkdir -p ${BUILD_DIRECTORY}
fi
cd ${BUILD_DIRECTORY} && \
../../${PACKAGE_NAME}-${PACKAGE_VERSION}/configure $4 --prefix=`pwd`/../$3 && \
make && \
make install && \
cd ../../
if [ $? -ne 0 ]; then
echo "Make ${PACKAGE_NAME} error!"
exit 1
fi
}
对于诸如此类的事情,它工作得很好
make_package "popt" "1.16" "arm_sdk" "--host=arm-linux-gnueabihf"
make_package "ncurses" "5.6" "arm_sdk" "--host=arm-linux-gnueabihf --without-ada"
但我被困在:
make_package "OpenIPMI" "2.0.28" "--host=arm-linux-gnueabihf LDFLAGS=\"-L`pwd`/build/arm_sdk/lib\" CPPFLAGS=\"-I`pwd`/build/arm_sdk/include -I`pwd`/build/arm_sdk/include/ncurses\""
问题来自于:
CPPFLAGS=\"-I`pwd`/build/arm_sdk/include -I`pwd`/build/arm_sdk/include/ncurses\"
因此我收到一个错误:
configure: error: unrecognized option: `-I/home/me/build/arm_sdk/include/ncurses"'
所以我被困在这里...有没有办法将这些配置参数作为参数传递给 bash 中的函数?
答案1
shell 在扩展参数(和变量等)之前会解析引号(和转义符等)。因此,像在第四个参数中所做的那样,在参数的值中加上引号不会产生任何作用。请参阅BashFAQ #50:“我试图将命令放入变量中,但复杂的情况总是失败!”, 和许多 以前的 问题。
通常,人们会尝试将多个参数存储在一个变量中,答案是使用数组;但您不能将数组作为参数传递,因此这对您不起作用。您可以做的是传递多个参数,因此$4
第一个包配置参数是,$5
第二个是,等等。因此,您可以像这样运行它:
make_package "OpenIPMI" "2.0.28" --host=arm-linux-gnueabihf LDFLAGS="-L$PWD/build/arm_sdk/lib" CPPFLAGS="-I$PWD/build/arm_sdk/include -I$PWD/build/arm_sdk/include/ncurses"
请注意,我用pwd
对变量的引用替换了命令的使用$PWD
——这不需要每次都创建新进程,因此效率更高。如果您确实想使用该pwd
命令,我建议使用$(pwd)
而不是反引号,因为它通常更具可读性,并且没有反引号所具有的语法怪异性。
要提取并使用函数中的参数,请使用以下命令:
# Store arguments starting at $4 in an array:
local package_configure_parameters=("${@:4}")
...
...
../../"${package_name}-${package_version}/configure" "${package_configure_parameters[@]}" --prefix="$PWD/../$package_install_dir" &&
...
看到我在定义和引用数组时使用的所有括号、方括号、引号等了吗?这些都是全部严格要求才能正常工作。我还在其他变量引用周围添加了引号,这大概不是必需的,但是一个好主意。shellcheck.net擅长指出这样的事情。我把变量名都小写,这通常是一个很好的做法,可以避免被任何具有特殊功能的全大写名称绊倒(如$PWD
)。小写或混合大小写的名称更安全,除非你想一些特殊的含义。
数组是 bash(以及 zsh 等)的一个功能,但并非所有 shell 都支持该功能。为了完整起见,如果您需要在可移植或非 bash 脚本中执行此操作,您可以将其捕获$1
为$3
变量(就像您已经做的那样),然后使用shift
它们从函数的参数列表中删除,并使用它们"$@"
获取配置参数:
make_package() {
local package_name="$1"
local package_version="$2"
local package_install_dir="$3"
shift 3 # Remove everything but the package config params from the arg list
...
../../"${package_name}-${package_version}/configure" "$@" --prefix="$PWD/../$package_install_dir" &&
...