美文网首页shell
shell脚本踩过的坑

shell脚本踩过的坑

作者: 陆_志东 | 来源:发表于2018-08-16 20:26 被阅读98次

首先shell脚本不允许在写表达式的时候加空格

比如:
a=1 正确语法
a = 1 错误语法

if语句块 坑

if 和条件语句块之间必须要有空格,[] 里面两端也必须要有空格
如果if语句写在同一行要加; 为了防止错误建议还是不要写一行
else 里面不允许出现空代码块,如果没有逻辑就不要写else
比如:

a=10
b=20
if [ ${a} -eq ${b} ]
then
  echo "相等"
else
  echo "不等"
fi

格式不要和上面的写法不一样,否则出错给你看

数字的比较要用数字运算符 -eq -ne -gt -lt -ge -le
字符的比较要用字符比较符 = != -z -n
运算符参考文章 点击

shell 函数返回值坑

return 的问题

shell 函数使用return语句只能返回整数,且还不能超出 0~255 这个范围,溢出会返回0值,这个一定要注意很大的坑
而且使用return返回的值 只有使用$?才能拿到,一般使用return 做函数的执行成功与否

怎么才能拿到想要的返回值

那怎么返回我们想要的值呢? 方法就是使用echo,shell 会把echo输出的值返回到调用函数的地方,这个相当于是其他高级语言的return,不过这个echo不会终止函数而已,shell 会把所有的echo 都返回到调用的地方,所以你要仔细确定你返回了多少个echo

注意:这里echo的坑

shell函数将echo的数据返回到调用的地方,如果调用函数的地方有变量接收,则数据赋值给变量,不会打印到终端,
如果没有变量接收,则shell会将数据输出到终端

下面是对echo的代码示范

  1 # /bin/bash
  2 
  3 a=1
  4 fund(){
  5     echo $a
  6     a=2
  7     echo $a    
  8 }
  9 
 10 fund
 11 echo $a

上面的这个脚本运行之后是  # 如果没有变量接收,数据按照echo格式默认输出
1
2
2
如果改成下面这样
  1 # /bin/bash
  2 
  3 a=1
  4 fund(){
  5     echo $a
  6     a=2
  7     echo $a     
  8 }   
  9 
 10 res=`fund`
 11 echo $a
输出结果是
1
没错答案就是1,函数内部的输出被赋值给了res,而不会输出到终端,至于为什么变量a还是1而不是2 下面是原因:
调用函数或者执行shell命令放在句首时不需要使用``或$()的,因为shell认识,但如果放在赋值表达式右边的话shell就不认识了,

至于答案为什么是1不是2,是因为
调用了``相当于开了一个子shell去运行程序,然后将结果返回,子shell是可以访问父shell的变量
但是子shell生成的变量以及所作的修改不影响父shell,还有shell中默认都是全局变量,无论是写在函数内还是函数外.如果想要让变量变成局部变量需要使用local
下面是对res 的打印
  1 # /bin/bash
  2 
  3 a=1
  4 fund(){
  5     echo $a
  6     a=2
  7     echo $a    
  8 }
  9 
 10 res=`fund`
 11 echo $res
 12 echo ${res[0]}
 13 echo ${res[1]}
 14 echo $a
打印结果是
1 2
1 2
    # 注意这是个空行
1
从上面看出返回的结果组合成了一个字符串,如果你想要所有的返回结果组成一个元祖
将上面的res=`fund` 修改为 res=(`fund`) 就可以了

怎么返回数组呢

如果你想返回数组,不好意思,不支持,不过还是通过其他渠道返回的

方式一: 使用echo

使用这种方式的弊端是如果你想在函数内部打印内容到终端,且还需要用变量接收就会很麻烦,只能够先返回结果,然后接收最后在打印

在shell 函数中,echo输出的值 和return输出的值返回给调用函数的地方
ok,我们就可以利用这个特性,将数组在函数内部拆分位为一个个元素,然后使用echo一个一个的返回元素,为什么要一个一个,因为echo也不支持返回数组,如果你返回了数组,它只会返回数组的第一个元素.所以我们一个一个的返回数据,然后在函数调用的地方重新组合

  1 # /bin/bash
  2 
  3 fun1(){
  4     a=(1 2 3)
  5     echo ${a[*]}
  6 }
  7 
  8 fun(){
  9     b=(`fun1`)   # 这里加括号是为了组合数组
 10     echo ${b[*]}
 11 }
 12 
 13 res=(`fun`)
 14 echo ${res[*]}

返回数组的方式二:使用全局变量的方式

  1 a=(4 5)
  2 fun(){
  3     a=(1 2 3)
  4     
  5     }
  6 b=(`echo ${a[*]}`)
  7 fun   -- 注意fun 一定不能放在等式的右边,比如 res=`fun` ,如果这样做就拿不到下面的输出了
  8 c=(`echo ${a[*]}`)
  9 echo ${b[*]}
 10 echo ${c[*]}
输出结果:
4 5
1 2 3
缺陷:使用这种方式只能直接调用函数或者linux命令,不能够``或者$()这样方式调用,涉及作用域问题,下面有讲解

在shell中默认都是全局变量,所以你可以在函数内部将数组赋值给全局变量,这样就能在调用函数之后拿到数组
不过一定要注意,不能带有`` 或者$()

  1 a=(4 5)
  2 fun(){
  3     a=(1 2 3)
  4 
  5     }
  6 b=(`echo ${a[*]}`)
  7 res=`fun`   -- 一旦加了`` 或者 $() 就不能拿到更改后的数组了,所以请使用上面的方式
  8 c=(`echo ${a[*]}`)
  9 echo ${b[*]}
 10 echo ${c[*]}
输出结果:
4 5
4 5

shell 调用能够直接在linux终端调用的命令

能够在linux终端运行的命令在shell脚本中也能够运行
如果命令放在句首不需要加`` 或者 $()
如果命令放在赋值运算符的右边将命令执行的结果赋值给变量,这个时候命令就需要加``和$()
调用shell自己定义的函数是一样的道理,如果放句首不需要`` or $() 如果放赋值运算符右边就需要加`` or $()
注意:
调用了``相当于开了一个子shell去运行程序,然后将结果返回,子shell是可以访问父shell的变量
但是子shell生成的变量以及所作的修改不影响父shell,还有shell中默认都是全局变量,无论是写在函数内还是函数外.如果想要让变量变成局部变量需要使用local

``和$()的作用域问题

`` 和 $() 是开了子shell去运行命令,然后将命令运行的结果回传,但是子shell所作的操作不会更改父shell变量数据,这里要注意一下,还有父shell不能使用除子shell返回之外的数据,但是子shell可以使用父shell的变量.

相关文章

网友评论

    本文标题:shell脚本踩过的坑

    本文链接:https://www.haomeiwen.com/subject/iytobftx.html