我正在尝试实现一个单独的命令,我认为它将是Bash(Bourne等)附带的正常'exit'和'return'shell内置函数的包装器,这个命令不受这些不兼容问题的困扰 . 因为如果我使用'exit 1'来结束错误级别为1的脚本,如果我获取该脚本,它将导致我所在的shell终止 .
同样,如果我使用return,它会遇到以下问题:a)它只返回调用函数,而不是在没有附加逻辑的情况下结束整个脚本运行 . b)如果我在主脚本中使用return并执行它,它将会出错而不是以一个级别终止 .
我提出的最佳解决方案是:
我写的所有shell脚本都以这个序言开头,以获得一些稳定的基本变量:
# Core Functions and Alias definitions Used For Script Setup
getScriptFile () { basename "${BASH_SOURCE[0]}" ; } # This filename as executed
getScriptPath () { local f="${BASH_SOURCE[0]}" ; local p ; while test -L "${f}"
do p="$( cd -P "$( dirname "${f}" )" && pwd )" ; f="$( readlink "${f}" )" &&
f="${p}/${f}" ; done ; p="$( cd -P "$( dirname "${f}" )" && pwd )" ;
printf "%s\n" "${p}" ; }
shopt -s expand_aliases
SCRIPTpath="$( getScriptPath ; )"
SCRIPTfile="$( getScriptFile ; )"
所以,现在我添加它:
testEq () { [ "${1}" = "${2}" ] ; } # True if there is equality
testMatch () { [[ ${1} =~ ${2} ]] ; } # True if ARG1 MATCHES the Extended RegEx in ARG2
testInt () { [ "${1}" -eq "${1}" ] 2>/dev/null ; } # I know this is okay with bash, to test with bourne
testIntLt () { testInt "${1}" && testInt "${2}" && [ "${1}" -lt "${2}" ] ; }
testSourced () { local c="0" ; local m="${#BASH_SOURCE[@]}" ;
until testEq "$( basename "${BASH_SOURCE[${c}]}" )" "${SCRIPTfile}" &&
testMatch "${FUNCNAME[${c}]}" "source|main" &&
testIntLt "${c}" "${m}" ; do ((c++)) ; done ;
if testEq "source" "${FUNCNAME[${c}]}" ; then return 0 ;
else return 1 ; fi ; } # True if calling script is sourced into environment
getValidTerminationCommand () { testSourced && printf "%s" "return" || printf "%s" "exit" ; }
alias finish='eval $( getValidTerminationCommand ; )'
......当我想突然完成一个剧本时,我使用了我的新完成命令,即
$ finish 5
现在,无论脚本是源还是执行,我都会得到退出代码5.对于错误类型的“退出”或“返回”没有错误 .
我在getScriptPath命令上有复杂性的原因是处理可能存在于符号链接下的文件系统路径上的脚本文件 .
testSourced复杂化的原因是测试需要工作,即使正在测试它的源代码的脚本是由调用脚本完成的,即它需要确保它正在测试它本身就是这样的事实 . 来源,而不是说一个调用脚本 .
现在,我知道这样做的正常方法很简单如下:
$ return 5 2>/dev/null || exit 5 # If I want to end a script with error level 5
问题是我无法弄清楚如何包装它来参数化它,以便我可以将它用作'finish'或'terminate'命令,它将使用此错误级别终止脚本,就好像我别名它,我可以做这没有返回的代码,或者如果它运行它然后它将返回调用函数/脚本,如果它有一个 .
必须有一个便携,简单的方式,而不是我在上面实现'完成'时提出的方法!?!当然这是标准的事情吗?
有人解决过这个吗?我错过了一些明显的东西吗
只是为了确认,我想要做的是: - 单个命令立即终止脚本 - 如果脚本被执行则相同的命令,sourced - 如果在函数中使用相同的命令,主脚本体或子函数 - 表现为如果脚本直接调用或源自可执行或源自的另一个脚本(或可能导致正在运行的脚本的n级执行),则相同 . - 用作Bash shell的标准命令(如果可能,Bourne),以便尽可能移植 .
任何人都有一些他们用于这项工作的工具?请告诉我?
在期待中感谢!?! :)
我以前尝试过的测试脚本:
#!/bin/bash
# Core Functions and Alias definitions Used For Script Setup
getScriptFile () { basename "${BASH_SOURCE[0]}" ; } # This filename as executed
getScriptPath () { local f="${BASH_SOURCE[0]}" ; local p ; while test -L "${f}"
do p="$( cd -P "$( dirname "${f}" )" && pwd )" ; f="$( readlink "${f}" )" &&
f="${p}/${f}" ; done ; p="$( cd -P "$( dirname "${f}" )" && pwd )" ;
printf "%s\n" "${p}" ; }
shopt -s expand_aliases
SCRIPTpath="$( getScriptPath ; )"
SCRIPTfile="$( getScriptFile ; )"
testEq () { [ "${1}" = "${2}" ] ; } # True if there is equality
testMatch () { [[ ${1} =~ ${2} ]] ; } # True if ARG1 MATCHES the Extended RegEx in ARG2
testInt () { [ "${1}" -eq "${1}" ] 2>/dev/null ; } # I know this is okay with bash, to test with bourne
testIntLt () { testInt "${1}" && testInt "${2}" && [ "${1}" -lt "${2}" ] ; }
testSourced () { local c="0" ; local m="${#BASH_SOURCE[@]}" ; until testEq "$( basename "${BASH_SOURCE[${c}]}" )" "${SCRIPTfile}" && testMatch "${FUNCNAME[${c}]}" "source|main" && testIntLt "${c}" "${m}" ; do ((c++)) ; done ; if testEq "source" "${FUNCNAME[${c}]}" ; then return 0 ; else return 1 ; fi ; } # True if calling script is sourced into environment
getValidTerminationCommand () { testSourced && printf "%s" "return" || printf "%s" "exit" ; }
alias finish='eval $( getValidTerminationCommand ; )'
anotherTestFunc ()
{
echo "anotherTestFunc ()"
finish 10
echo "anotherTestFunc () finish"
}
testFunc ()
{
echo "testFunc ()"
anotherTestFunc
echo "testFunc () finish"
}
echo test start
testFunc
echo more outside text