Shell中处理方法返回值问题

同步发表:http://blog.hacktons.cn/2017/12/13/shell-func-return/
背景
通过shell编程,写一些工具批处理的时候,经常需要自定义函数。更复杂点的情况下,可能有需要返回一个值。
由于在shell的世界中,并不像其他编程语言,它不支持我们所熟悉的方法返回。本文一起总结一下如何优雅的解决返回值问题?
测试程序
我们一般通过$?来获取上一个语句的输出。看一下下面得测试语句:
新建testReturn脚本
returnString(){
return $1
}
returnString $1
result=$?
echo "result=$result"
现在我们有一个testReturn的脚本,里面有一个returnString的方法,我们希望它能够直接返回我们输入的参数。
当我们分别以hello,500,12作为输入参数时,他的执行和输出情况是一样的么?
./testReturn hello
./testReturn 500
./testReturn 12
在心中试着猜一下可能的情况,现在我们来揭晓答案:
程序输出情况
在执行hello的时候,并没有输出hello,而是报了一个return只接受数字类型的错误
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
./testReturn: line 23: return: hello: numeric argument required
result=255
在执行500的时候,页没有输出500,而是输出了244
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=244
执行12的时候,终于正确了,返回12
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12
异常分析
现在我们分析一下returnString这个方法,为什么会有这么多种输出情况呢?
首先他的写法显然是不严谨的,但也不是完全错误,比如输入12他就正确返回了。
return本身是shell里面的buildin函数,笔者总结了下,他有以下几个特征:
- return可以返回数字状态,常常用于返回0,1,标识一个函数执行后是否成功
- 注意return不可以返回非数字类型
- 同时数字类型也有可能发生溢出现象
全局变量
如果我们就是要返回一个字符串,怎么办呢?可以通过定义全局变量来进行赋值,类似于静态变量/成员变量的写法,我们让他的作用域穿透整个上下文。
result=""
returnString(){
result=$1
}
returnString $1
echo "result=$result"
再看一下输出,得到了我们需要的结果:
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12
但是这样写,会污染全局变量,并且result这个变量很容易在内部和外部都被修改,导致内部修改失效。
eval
除了return,还有其他一些buildin的关键字,比如eval,local。
默认在当前脚本定义的变量都是全局变量,在方法中则可以通过local来定义局部变量,这样可以避免全局变量污染.
同时结合eval赋值语句,来实现变量的修改
returnString(){
local __result=$2
eval $__result=$1
}
returnString $1 result
echo "result=$result"
同样我们也得到了希望的结果
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12
echo
最后在介绍一种方法,通过echo输出,结合command substitution。
这个command substitution也没有找到比较合适的翻译,姑且按字面意思翻译命令替换。
如果你的方法内部只有一处echo输出,那么也可以利用她来进行值得返回,不过这个就有点局限性,一定要确保方法内只有一次输出,否则就会出现赋值内容过多。
returnString(){
local __result=$1
echo $__result
}
# 或者 result=`returnString $1`
result=$(returnString $1)
echo "result=$result"
同样可以得到预期结果
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn hello
result=hello
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 500
result=500
aven-mac-pro-2:avenwu.github.io aven$ ./testReturn 12
result=12
越界问题
现在我们已经有几种办法可以返回字符串了,那么return返回数字有时候正确,有时候又不正确是为什么呢?
我们知道return原本就是用于返回执行状态的,比如0,1.那么我们在返回500的时候,实际上是数据溢出了。
根据测试,我们推断shell的内置return承接返回值用的是一个字节的大小,也就是8位,最多可以输出无符号0-255的整形,范围之外的数据全部溢出显示。因此在使用return的时候,务必留意数值大小。
小结
通过shell命令可以很方便的写出一些小脚本,但是如果遇到逻辑复杂,建议通过其他更合适的预览来实现,比如Python,Golang之类。
Shell中处理方法返回值问题的更多相关文章
- SpringMVC中 controller方法返回值
1)ModelAndView @RequestMapping(value="/itemEdit") public ModelAndView itemEdit(){ //创建模型视图 ...
- java中的方法返回值使用泛型,实现灵活的返回值类型
痛点: 使用Mybatis框架的时候,想封装一个底层JDBC控制器,用于提供和Mybatis交互的增删改查接口(公用的接口),但由于公用的查询方法可能是用户自定义的任意一个和表对应的java ...
- C#中部分方法返回值类型为什么只能是void?
这个问题答案选至<C#入门经典> 如果方法具有返回类型,那就可以作为表达式的一部分: x=Manipulate(y,z); 如果没有给部分方法提供实现代码,编译器就会在使用该方法的所有地方 ...
- Spring MVC中 controller方法返回值
1.返回ModelAndView 定义ModelAndView对象并返回,对象中可添加model数据.指定view 2.返回String 1.表示返回逻辑视图名 model对象通过 model.add ...
- Android onTouchEvent事件中onTouch方法返回值介绍
1.若return false说明没有成功执行onTouch事件,在执行完onTouch里面的代码之后,onTouch事件并没有结束.因此某些组件如Gallery会自动执行它所在view里onTouc ...
- 060、Java中定义有返回值有参数的方法
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- C# 方法返回值的个数
方法返回值类型总的来说分为值类型,引用类型,Void 有些方法显示的标出返回值 public int Add(int a,int b) { return a+b; } 有些方法隐式的返回返回值,我们可 ...
- 使用Result代替ResultSet作为方法返回值
在开发过程中,我们不能将ResultSet对象作为方法的返回值,因为Connection连接一旦关闭,在此连接上的会话和在会话上的结果集也将会自动关闭,而Result对象则不会发生这种现象,所以在查询 ...
- SpringMVC第五篇【方法返回值、数据回显、idea下配置虚拟目录、文件上传】
Controller方法返回值 Controller方法的返回值其实就几种类型,我们来总结一下-. void String ModelAndView redirect重定向 forward转发 数据回 ...
随机推荐
- Struts2实现文件上传下载功能(批量上传)
今天来发布一个使用Struts2上传下载的项目, struts2为文件上传下载提供了好的实现机制, 首先,可以先看一下我的项目截图 关于需要使用的jar包,需要用到commons-fileupload ...
- Django开发小型站之前期准备(一)
语言:python3.5 工具:JetBrains PyCharm virtualenvwrapper优点: 1.使不同的应用开发环境独立 2.环境升级不影响其他应用,也不会影响全局的python环境 ...
- ACM课程总结
当我还是一个被P哥哥忽悠来的无知少年时,以为编程只有C语言那么点东西,半个学期学完C语言的我以为天下无敌了,谁知自从有了杭电练习题之后,才发现自己简直就是渣渣--咳咳进入正题: STL篇: 成长为一名 ...
- zip 安装mysql 和遇到的坑
在官网下载了mysql 社区版的,官方网址:https://dev.mysql.com/downloads/mysql/ 解压后发现里面没有安装快捷方式,才知道是zip解压,dos窗口安装.这就比界面 ...
- CSS实现父元素半透明,子元素不透明
CSS实现父元素半透明,子元素不透明. 很久以来大家都习惯使用opacity:0.5在新式浏览器里实现半透明,而对IE较旧的版本使用filter:Alpha(opacity=0.5)的滤镜来实现半透明 ...
- 疑似CPU或者内存故障导致进程崩溃
我们有一个服务跑在微软云的所有宿主机上.最近发现某一台机器上该服务进程持续崩溃.崩溃原因是访问了一个无效指针,对应的代码如下 serviceListIniBuffer.AppendF("Se ...
- openstack学习心得:keystone 常用命令(M版)
查看用户列表 openstack user list 查看用户具体信息 usage: openstack user show [-h] [-f {html,json,json,shell,table, ...
- phpcms 的getcache()函数
一直没有去研究phpcms 的getcache()函数是干嘛的,今天有空去看了一下,原来就那样. 1 function getcache($name, $filepath='', $type='fil ...
- C#移位运算(左移和右移)
C#是用<<(左移) 和 >>(右移) 运算符是用来执行移位运算. 左移 (<<) 将第一个操作数向左移动第二个操作数指定的位数,空出的位置补0. 左移相当于乘. ...
- 基于 Aspose.Cells与XML导入excel 数据----操作类封装
前言 导入excel数据, 在每个项目中基本上都会遇到,第三方插件或者基于微软office,用的最多的就是npoi,aspose.cells和c#基于office这三种方式,其中各有各的优缺点,在这也 ...