在 bash 中,如何将返回值存储在变量中?
- 2024-11-12 08:36:00
- admin 原创
- 20
问题描述:
我知道 Linux 中的一些非常基本的命令,并且正在尝试编写一些脚本。我编写了一个函数,用于计算一个 5 位数字中最后 2 位数字的总和。该函数应将这个结果总和连接到最后 2 位数字之间并返回它。我想要返回这个值的原因是我将在另一个函数中使用该值。
例如:如果我有 12345,那么我的函数将计算 4 + 5 并返回 495。
#!/bin/bash
set -x
echo "enter: "
read input
function password_formula
{
length=${#input}
last_two=${input:length-2:length}
first=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $2}'`
second=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $1}'`
let sum=$first+$second
sum_len=${#sum}
echo $second
echo $sum
if [ $sum -gt 9 ]
then
sum=${sum:1}
fi
value=$second$sum$first
return $value
}
result=$(password_formula)
echo $result
我尝试回应并查看结果,但我得到的输出如下所示。
-bash-3.2$ ./file2.sh
+++ password_formula
+++ echo 'enter: '
+++ read input
12385
+++ length=8
+++ last_two=85
++++ echo 85
++++ sed -e 's/(.)/ /g'
++++ awk '{print $2}'
+++ first=5
++++ echo 85
++++ sed -e 's/(.)/ /g'
++++ awk '{print $1}'
+++ second=8
+++ let sum=5+8
+++ sum_len=2
+++ echo 5
+++ echo 8
+++ echo 13
+++ '[' 13 -gt 9 ']'
+++ sum=3
+++ value=835
+++ return 835
++ result='enter:
5
8
13'
++ echo enter: 5 8 13
enter: 5 8 13
我还尝试将结果打印为:
password_formula
RESULT=$?
echo $RESULT
但这给出了一些未知的值:
++ RESULT=67
++ echo 67
67
我如何才能正确地存储正确的值并在屏幕上打印(以仔细检查)?
解决方案 1:
最简单的答案:
函数的返回代码只能是 0 到 255 范围内的值。要将此值存储在变量中,您必须像本例中那样执行:
#!/bin/bash
function returnfunction {
# example value between 0-255 to be returned
return 23
}
# note that the value has to be stored immediately after the function call :
returnfunction
myreturnvalue=$?
echo "myreturnvalue is "$myreturnvalue
解决方案 2:
返回值(又称退出代码)是 0 到 255 范围内的一个值(含)。它用于指示成功或失败,而不是返回信息。超出此范围的任何值都将被包装。
要返回信息(例如您的电话号码),请使用
echo "$value"
要打印您不想捕获的其他信息,请使用
echo "my irrelevant info" >&2
最后,为了捕捉它,使用你所做的:
result=$(password_formula)
换句话说:
echo "enter: "
read input
password_formula()
{
length=${#input}
last_two=${input:length-2:length}
first=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $2}'`
second=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $1}'`
let sum=$first+$second
sum_len=${#sum}
echo $second >&2
echo $sum >&2
if [ $sum -gt 9 ]
then
sum=${sum:1}
fi
value=$second$sum$first
echo $value
}
result=$(password_formula)
echo "The value is $result"
解决方案 3:
这很容易,您需要回显需要返回的值,然后像下面这样捕获它
demofunc(){
local variable="hellow"
echo $variable
}
val=$(demofunc)
echo $val
解决方案 4:
使用特殊 bash 变量“$?”如下:
function_output=$(my_function)
function_return_value=$?
解决方案 5:
上面的答案建议将函数更改为回显数据而不是返回数据,以便可以捕获数据。
对于无法修改且需要将返回值保存到变量的函数或程序(例如test
/ [
,它返回 0/1 成功值),请$?
在命令替换中 echo:
# Test if we're remote.
isRemote="$(test -z "$REMOTE_ADDR"; echo $?)"
# Or:
isRemote="$([ -z "$REMOTE_ADDR" ]; echo $?)"
# Additionally you may want to reverse the 0 (success) / 1 (error) values
# for your own sanity, using arithmetic expansion:
remoteAddrIsEmpty="$([ -z "$REMOTE_ADDR" ]; echo $((1-$?)))"
例如
$ echo $REMOTE_ADDR
$ test -z "$REMOTE_ADDR"; echo $?
0
$ REMOTE_ADDR=127.0.0.1
$ test -z "$REMOTE_ADDR"; echo $?
1
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
1
$ unset REMOTE_ADDR
$ retval="$(test -z "$REMOTE_ADDR"; echo $?)"; echo $retval
0
对于打印数据但也有返回值需要保存的程序,返回值将从输出中单独捕获:
# Two different files, 1 and 2.
$ cat 1
1
$ cat 2
2
$ diffs="$(cmp 1 2)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [1] Diffs: [1 2 differ: char 1, line 1]
$ diffs="$(cmp 1 1)"
$ haveDiffs=$?
$ echo "Have differences? [$haveDiffs] Diffs: [$diffs]"
Have differences? [0] Diffs: []
# Or again, if you just want a success variable, reverse with arithmetic expansion:
$ cmp -s 1 2; filesAreIdentical=$((1-$?))
$ echo $filesAreIdentical
0
解决方案 6:
这是由于echo
语句。您可以将回声切换为打印并返回echo
。以下作品
#!/bin/bash
set -x
echo "enter: "
read input
function password_formula
{
length=${#input}
last_two=${input:length-2:length}
first=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $2}'`
second=`echo $last_two| sed -e 's/(.)/ /g'|awk '{print $1}'`
let sum=$first+$second
sum_len=${#sum}
print $second
print $sum
if [ $sum -gt 9 ]
then
sum=${sum:1}
fi
value=$second$sum$first
echo $value
}
result=$(password_formula)
echo $result
解决方案 7:
可以使用类似的东西,并且仍然保持return
(返回控制信号)和echo
(返回信息)和日志记录语句(打印调试/信息消息)的含义。
v_verbose=1
v_verbose_f="" # verbose file name
FLAG_BGPID=""
e_verbose() {
if [[ $v_verbose -ge 0 ]]; then
v_verbose_f=$(tempfile)
tail -f $v_verbose_f &
FLAG_BGPID="$!"
fi
}
d_verbose() {
if [[ x"$FLAG_BGPID" != "x" ]]; then
kill $FLAG_BGPID > /dev/null
FLAG_BGPID=""
rm -f $v_verbose_f > /dev/null
fi
}
init() {
e_verbose
trap cleanup SIGINT SIGQUIT SIGKILL SIGSTOP SIGTERM SIGHUP SIGTSTP
}
cleanup() {
d_verbose
}
init
fun1() {
echo "got $1" >> $v_verbose_f
echo "got $2" >> $v_verbose_f
echo "$(( $1 + $2 ))"
return 0
}
a=$(fun1 10 20)
if [[ $? -eq 0 ]]; then
echo ">>sum: $a"
else
echo "error: $?"
fi
cleanup
在这里,我将调试消息重定向到单独的文件,由尾部监视,如果有任何更改,则打印更改,trap
用于确保后台进程始终结束。
此行为也可以通过使用重定向来实现/dev/stderr
,但是在将一个命令的输出通过管道传输到其他命令的输入时可以看到差异。
解决方案 8:
好的,如果我们设置了,那么这个问题的主要答案是有问题的errexit
,例如
#!/bin/bash
set -o errexit
my_fun() {
# returns 0 if the first arguments is "a"
# 1 otherwise
[ "${1}" = "a" ]
}
my_fun "a"
echo "a=$?"
my_fun "b"
echo "b=$?"
在这种情况下,当结果不是 0 时,bash 就会退出,例如,这只会打印一行。
./test_output.sh
a=0
正如已经说过的,这里可能最正确的答案是这样的:
# like this
my_val=0 ; my_fun "a" || my_val=$?
echo "a=${my_val}"
# or this
my_fun "b" && my_val=0 || my_val=$?
echo "b=${my_val}"
这将正确打印所有值,且无错误
a=0
b=1
我不知道“echo”实现是否最正确,因为我仍然不清楚 $() 是否创建了子 shell。例如,我有一个函数,它在函数中打开一个文件描述符并返回数字,似乎 bash 在退出该函数后关闭了 fd。(如果有人能在这里帮助我 :-)
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件