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转发 数据回 ...
随机推荐
- C++计时器:毫秒级和微秒级
1.毫秒级 使用GetTickCount()获取系统启动所经过的毫秒数 #include<iostream> using namespace std; int main(){ DWORD ...
- @RequestBody对象为空,异常Required request body is missing
1.异常 org.springframework.http.converter.HttpMessageNotReadableException: Required request body is mi ...
- 手工搭建ABP框架(1) - Web项目
为了防止不提供原网址的转载,特在这里加上原文链接: http://www.cnblogs.com/skabyy/p/7295533.html ABP是 ASP.NET Boilerplate Proj ...
- day2--计算机基础
一.服务器 1u服务器,1u=4.45cm 戴尔服务器种类: 电脑主机组成 主板.CPU.内存.硬盘.显卡.声卡等等. 运维关注三大部件:CPU.内存.硬盘(Disk) 电源,考虑使用双电服务器,电源 ...
- 使用 ConfigSource 特性 拆分 Web.config 文件
一个大项目里可能会有非常多个配置参数,有.Net自己支持的配置(比如WCF,AppSettings),还有一部分是自定义的配置(比如继承自ConfigurationSection和Configurat ...
- 前端基于react,后端基于.net core2.0的开发之路(2) 开发环境的配置,注意事项,后端数据初始化
前端环境配置 项目介绍文章:前端基于react,后端基于.net core2.0的开发之路(1) 介绍 1.VSCode安装 下载地址:https://code.visualstudio.com/Do ...
- Datatable转换为Json
/// <summary> /// Datatable转换为Json /// </summary> /// <param name="table"&g ...
- 71、django之Ajax续
接上篇随笔.继续介绍ajax的使用. 上篇友情连接:http://www.cnblogs.com/liluning/p/7831169.html 本篇导航: Ajax响应参数 csrf 跨站请求伪造 ...
- ASP.Net Controls 用法大全
The FindControl method of the System.Web.UI.Control class appears simple enough to use. In fact, the ...
- 【python】Python的单例模式
原文:http://blog.csdn.net/ghostfromheaven/article/details/7671853 单例模式:保证一个类仅有一个实例,并提供一个访问他的全局访问点. 实现某 ...