Linux 论据及;多个Bash脚本中的选项操作
编辑(2月24日):有关更多信息、示例和代码,请参阅文章底部 最近工作中出现了一些停机时间,所以我决定学习一些Bash脚本并自动化构建产品的过程。以下是我们设置的简化版本:Linux 论据及;多个Bash脚本中的选项操作,linux,bash,shell,unix,scripting,Linux,Bash,Shell,Unix,Scripting,编辑(2月24日):有关更多信息、示例和代码,请参阅文章底部 最近工作中出现了一些停机时间,所以我决定学习一些Bash脚本并自动化构建产品的过程。以下是我们设置的简化版本: 有三种类型的代码库-库、旧接口和新接口 构建分为两个步骤——1设置环境(所有变量)和2编译可执行文件/包;这两项都是通过脚本完成的,其中一些脚本采用命令行参数,而另一些脚本不采用 每个代码库使用不同的set env和build脚本(因此脚本目录可以有libs set env.sh,old if set env.sh,new
- 有三种类型的代码库-库、旧接口和新接口
- 构建分为两个步骤——1设置环境(所有变量)和2编译可执行文件/包;这两项都是通过脚本完成的,其中一些脚本采用命令行参数,而另一些脚本不采用
- 每个代码库使用不同的
和set env
脚本(因此脚本目录可以有build
,libs set env.sh
,old if set env.sh
,new if set env.sh
,等等。)libs build.sh
- 检测我当前所在的代码库目录
- 分析任意数量的命令行选项/参数。我一直在尝试使用
。getopts
- 有些选项只是标志(例如用于详细输出的
),有些选项需要一个值(例如-code>版本3.0)-v
- 有些选项只是标志(例如用于详细输出的
- 运行相应的
脚本set env
- 运行相应的
脚本build
.sh
文件中。我遇到了一个问题,一些构建脚本会试图读取我自己的命令行参数,就好像它们是为它们准备的一样。因此,我运行类似于~/myscript.sh-v的程序,会得到如下错误
~/scripts/build-base-libs.sh: line X: cd: -v: invalid option
cd: usage: cd [-L|-P] [dir]
因为build base libs.sh
检查传递给它的参数是否为--debug
或--release
,如果不是(例如,如果是-v
),它将其视为文件路径并将其传递给cd
调用。这对于原始脚本来说很好,但是它弄乱了我的包装。所以问题#1:我是否仍然可以将所有内容都放在一个.sh文件中,但以某种方式避免这个问题(可能只使用一个子集或不使用原始命令行参数调用相应的构建
脚本?)
当这不起作用时,我尝试拆分功能-因此我将使用mysetenv.sh和mybuild.sh,并通过自己的命令行参数解析前者,然后使用任何原始选项或不使用任何原始选项调用后者(因此,如果我运行~/mysetenv.sh-g-version 3.0
,我可以选择是使用-g
、使用-version 3.0
调用~/mybuild.sh
,还是两者都不调用)。除了我对Bash的了解显然不够,无法运行它-当我运行~/mysetenv.sh
时,我实际上看不到我应该从mybuild.sh
中看到的任何输出。我怀疑它与子进程和子shell有关,但我只是不知道…我还尝试在~/.bashrc 然后让该函数调用其他两个脚本,但遇到了相同的问题
那么…请给我提个建议好吗
---编辑(2月24日)---
为了简单起见,我减少了可能出现的情况的数量。让我们假设我将使用以下选项和参数运行脚本:
~/myscript.sh-c-v版本3.0——调试
如果-c
只是设置了一些标志,-v
使得我需要在build命令的末尾附加“ver.3.0”,而--debug
是一个由build
脚本处理的参数,它不是我自己的(因此,如果提供了,我需要传递它)
通常,我的脚本应执行以下操作:
1) 通过(我的自定义)选项进行解析
这些没什么特别的。我重置OPTIND变量,以确保始终读取所有内容
OPTIND=1
while getopts "cv:" OPTION; do
"c") echo "Option -c" ;;
"v") echo "Option -v ( = ${OPTARG})" ;;
"?") echo "Unknown option."
done
2) 选择setenv
命令并运行它
setenv
和build
脚本都是为处理命令行参数而设计的,但我自己从来没有将任何参数传递给setenv
s-仅传递给build
s,甚至只有当参数是-v
选项的值时。所以我的setenv
脚本是/development/scripts/setenv_script.sh
,我想运行
/development/scripts/setenv_script.sh#没有选项,忽略它--从以前调试
首先,不忽略--debug
(因为即使没有${@:OPTIND}
部分,我也会得到完全相同的错误):
我得到以下错误:
eval . /development/scripts/setenv_script.sh
/development/scripts/setenv_script_2.sh: line 104: cd: ver.3.0: No such file or directory
setenv_script_2.sh
的相关章节包括:
60 for option in $*; do
61 case $option in
62 "--release") ... ;;
63 "--debug") ... ;;
64 "--help") ... ;;
65 *) src_path=$option ;;
66 esac
67 done
...
103 if [ -n "${src_path}" ]; then
104 src_dir=$(cd -P ${src_path}; pwd -P)
105 else
106 src_dir=$(pwd -P)
因此,据我所知,setenv_script.sh
被调用时没有参数(如echo
;虽然我希望得到--debug
…),这是我想要的,但它调用的其中一个脚本仍然将“ver.3.0”视为参数,我不希望这样做。我希望将“3.0版”传递给build
脚本,并且setenv
运行时不带任何参数
我有没有办法更新$@
/$*
?因此,在阅读了我的选项后,我可以说“好的,有0个命令行参数,运行setenv_script.sh
传递给它及其子级”?然后,当我完成这项工作时,我可以说“好的,现在让我们运行build.sh
,但是如果设置了-v
选项,我们将把它的值作为唯一的命令行参数”
3) 选择build
命令并运行它
还不太清楚。如果您不展示一些代码,就很难回答您的任何问题。我支持Markku,请提供一些代码。另一方面,我认为heri中没有“子脚本”的论点
60 for option in $*; do
61 case $option in
62 "--release") ... ;;
63 "--debug") ... ;;
64 "--help") ... ;;
65 *) src_path=$option ;;
66 esac
67 done
...
103 if [ -n "${src_path}" ]; then
104 src_dir=$(cd -P ${src_path}; pwd -P)
105 else
106 src_dir=$(pwd -P)