Linux 论据及;多个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

编辑(2月24日):有关更多信息、示例和代码,请参阅文章底部

最近工作中出现了一些停机时间,所以我决定学习一些Bash脚本并自动化构建产品的过程。以下是我们设置的简化版本:

  • 有三种类型的代码库-库、旧接口和新接口
  • 构建分为两个步骤——1设置环境(所有变量)和2编译可执行文件/包;这两项都是通过脚本完成的,其中一些脚本采用命令行参数,而另一些脚本不采用
  • 每个代码库使用不同的
    set env
    build
    脚本(因此脚本目录可以有
    libs set env.sh
    old if set env.sh
    new if set env.sh
    libs build.sh
    ,等等。)
所以。我想做的是创建一些(组合)Bash函数和脚本,它们将:

  • 检测我当前所在的代码库目录
  • 分析任意数量的命令行选项/参数。我一直在尝试使用
    getopts
    • 有些选项只是标志(例如用于详细输出的
      -v
      ),有些选项需要一个值(例如-code>版本3.0)
  • 运行相应的
    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)