shell学习2

函数的使用

function hello()
{
    echo "Hello SHell.";
	  return 1;
}
echo "method begin..."
hello
echo "method end..."

# method begin...
# Hello SHell.
# method end...

在 Shell 中,参数返回可以显示加 return 返回。如果不加,将以最后一条命令运行结果,作为返回值。返回值只能正整数,并且范围在 0 - 255。

函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,1表示第一个参数,2表示第二个参数…

funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "第十个参数为 $10 !"
    echo "第十个参数为 ${10} !"
    echo "第十一个参数为 ${11} !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

输出结果:

第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

注意,10 不能获取第十个参数,获取第十个参数需要{10}。当n>=10时,需要使用${n}来获取参数。

输出的重定向

在写 Shell 脚本的时候,我们经常会想将命令的输出结果保存到文件中,或者将命令的执行结果保存到日志记录中。这时候就需要把命令的输出结果重定向。而要进行重定向,就要了解 Linux 的输入输出流。

在 Linux 中有三个经常用到的输入输出流,他们分别是:

  • 标准输入(stdin)
  • 标准输出(stdout)
  • 标准错误(stderr)

在 Linux 系统中,系统保留了 0(标准输入)、1(标准输出)、2(标准错误) 三个文件描述符分别代表它们。

标准输入指的是从键盘这些标准输入设备读取到的数据。一般情况下标准输入重定向的很少用到.

标准输出则是通过屏幕输出的这些数据。我们可以通过标准输出重定向来让数据保存到文件里。

$ echo "hello shell" > out.txt
$ cat out.txt
hello shell
# echo 命令的输出并没有在屏幕上打印,而是保存在了out.txt文件中。

其实上面这种方式和echo “hello” 1> out.txt这条命令的结果是一样的。或许是因为标准输出重定向比较频繁,所以就把数字 1 省略了。

标准错误是指输出的错误信息。例如当我们运行一条错误的指令时,控制台会提示凑无信息,这些就是错误信息。如果我们要重定向错误信息到文件中,我们可以用2>这个操作符。

$ ls +
ls: +: No such file or directory
$ ls + 2> error.txt
$ cat error.txt
ls: +: No such file or directory

# 通过2>这个操作符,我们将标准错误重定向到了 error.txt 文件中了。

文件判断

文件测试运算符用于检测文件的各种状态和属性,目前支持的运算符如下:

  • -b file:是否块设备文件
  • -c file:是否字符设别文件
  • -d file:是否目录
  • -f file:是否普通文件
  • -g file:文件是否设置了 SGID 位
  • -k file:是否设置了粘着位
  • -p file:文件是否有名管道
  • -u file:文件是否设置了 SUID 位
  • -r file:文件是否可读
  • -w file:文件是否可写
  • -x file:文件是否可执行
  • -s file:文件是否为空(文件大小是否大于0),不为空返回 true。
  • -e file:文件(包括目录)是否存在

要特别注意的是-s file判断文件是否为空时,不为空才返回true。

变量 file 表示文件 /User/hello.sh,它的大小为 52 字节,具有 rwx 权限。下面的代码,将检测该文件的各种属性:

#!/bin/bash

file="/User/hello.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $file ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi
if [ -f $file ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $file ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

算术运算符

在 Shell 中,利用 expr 命令再加上算术运算符可以实现数值运算。目前支持的算术运算符有:

  • +:加法
  • -:减法
  • *:乘法
  • /:除法
  • %:取余
  • =:赋值
  • ==:相等
  • !=:不相等

在 原生 Bash 不支持简单的数学运算,所以在 Shell 语言中的运算都是通过其他命令来实现的,其中最常用的就是 expr 命令。

#!/bin/sh
val=`expr 2 + 2`
echo "Total value : $val"
# Total value : 4

上面的 ` 符号叫做反引号,作用是将符号内的命令结果赋值给左边的变量。

数组

Shell 中有数组这个概念,数组中可以存放多个值。但 Shell 只支持一维数组,不支持多维数组,初始化时不需要定义数组大小。与大部分编程语言类似,数组元素的下标由0开始。

Shell 数组用括号来表示,元素用「空格」符号分割开,语法格式如下:

array_name=(value1 value2 ... valuen)

#!/bin/bash
my_array=(A B "C" D)

也可以使用下标来定义数组:

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

读取数组元素值的一般格式是:${array_name[index]}

#!/bin/bash
my_array=(A B "C" D)
echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"

结果:

$ chmod +x test.sh 
$ ./test.sh
第一个元素为: A
第二个元素为: B
第三个元素为: C
第四个元素为: D

获取数组中的所有元素 使用@ 或 * 可以获取数组中的所有元素

#!/bin/bash

my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D

echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
echo "数组元素个数: ${#my_array[*]}"
echo "数组元素个数: ${#my_array[@]}"

结果:

$ chmod +x test.sh 
$ ./test.sh
数组的元素为: A B C D
数组的元素为: A B C D
数组元素个数: 4
数组元素个数: 4

特殊符号[]、[[]]、(())、$(())、()

括号和括号组成的特殊标识,例如:[]、[[]]、(())、$(())、()

test命令

test {EXPRESSION}

if test "a" == "a"
then 
	echo match!
fi

[]

[] 符号的作用与 test 命令一样,都用于判断表达式的真假。只不过 [] 将表达式括起来了,更加易读。上面的例子用 [] 重写就会变成这样:

if [ "a" == "a" ]
then 
	echo match!	
fi

if [ $a -gt 10 -a $a -lt 15 ]
then 
	echo match!	
fi

[[]]

[[]] 符号与 [] 符号的区别是,在 [[]] 符号里,我们引用变量时可以不再用 $ 符号了,而且还可以使用 && 和 || 运算符。

像上面判断变量 a 的范围,我们在 [] 符号中,只能使用 -gt 、-a、-lt等操作符。但如果用[[]]实现,我们就可以用上&&和||操作符:

a=12
if [[ a -gt 10 && a -lt 15 ]]
then 
	echo match!	
fi

let命令

a=10
let b=a+10
echo $b

在 let 命令中的变量,不需要使用 $ 符号就可以使用。像上面的 a 变量,其实一个变量,但是在第 2 行的 let 语句不需要使用 $ 符号也能成功运算。

(())

这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。在这个符号里,我们可以进行整数运算,它的作用和 let 命令一样。

a=10
(( b = a + 10 ))
echo $b

或者我们可以将计算结果作为表达式,如果结果是 0 表示假,其余全部是真。

a=10
if (( a + 10 ))
then
	echo true
fi

a=10
if (( a <= 12 && a > 0))
then 
  echo great than 10
fi

$(())

和上面的差不多,但是不会像命令一样有返回值,而是会像变量一样把运算结果替换出来。

a=10
b=$(( a <= 12 && a > 0))
echo $b

输出:1

a=10
b=$(( a <= 12 && a < 0))
echo $b

输出:0

因此如果要让它作为一个表达式的话,就要结合 [] 符号。例如:

a=10
if [ $(( a <= 12 && a > 0)) -eq 1 ]
then 
  echo great than 10
fi

对于 (()) 符号而言只有 bash 这个 Shell 有,而 $(()) 则是所有 Shell 都有,更为通用。

()

() 符号表示括号中作为一个子 Shell 运行,运行结果不干扰外层的 Shell。

a=2
(a=1)
echo $a

输出是:2

因为括号括起来是一个子 Shell,不影响外层 Shell 的运行,所以对 a 赋值为 1 不影响外层结果,外层的 a 变量还是 2。

利用上面子 Shell 这个特性,我们在写 Shell 脚本的时候可以做到不切换当前目录而在其他目录干点事儿。例如:

(cd hello; echo "Hello Shell" > hello.txt); pwd; cat hello/hello.txt

上面我进入了子目录 hello,并创建了一个 hello.txt 文件。输出结果是:

Hello Shell

可以看到我当前目录没有改变,但是文件已经创建成功了。

{} 大括号

用法与上面介绍的指令群组非常相似,但有个不同点,它在当前的 shell 执行,不会产生 subshell。 单纯只使用大括号时,作用就像是个没有指定名称的函数。

a=2
{ a=1; }
echo $a

上面输出:1

这个用法和 () 用法的区别有两个:

  • 大括号 {} 里的运算是在当前 Shell 运行,会影响外层结果,而括号 ()的不会。
  • 大括号里最后一个语句必须要用 ; 分号结束,否则出错,而括号 () 的并没有这个要求。

逻辑运算符

逻辑运算符有三个,分别是:非运算、或运算、与运算。

  • !:非运算符。
  • -o:或运算符。
  • -a:与运算符。

因为 Shell 中并没有布尔类型,所以非运算符主要是对表达式取反。

#!/bin/bash
a=10
b=20
# 非运算
if !(( a == b ))
then
   echo "a is not equal to b" 
fi
# 或运算
if [ $a -lt 100 -o $b -gt 100 ]
then
   echo "a < 100 or b > 100" 
fi
# 与运算
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "a < 100 and b > 15" 
fi

值得注意的是,因为 Shell 语言并没有布尔型。所以如果你尝试在非运算符后面跟上一个「布尔值」,那么你会得到错误的结果。

#!/bin/bash
result=true
if [ !$result ]
then 
  echo "Hello"
fi

按照我们的理解,上面的例子应该不会打印出 Hello 字符,但实际结果是会打印。这是因为 Shell 中根本就没有布尔类型的值,所以 if 表达式中的字符串会被当成是一个字符串,字符串肯定就是 true 了,所以就会打印 Hello。其实如果我们随便输入一串字符,结果还是会输出 Hello。

关系运算符

关系运算符只支持数值运算,不支持字符运算。

  • -eq:检测两个数是否相等,相等返回 true。
  • -ne:检测两个数是否不相等,相等返回 true。
  • -gt:检测左边的数是否大于右边的,如果是返回 true。
  • -lt:检测左边的数是否小于右边的,如果是返回 true。
  • -ge:检测左边的数是否大于等于右边的,如果是返回 true。
  • -le:检测左边的数是否小于等于右边的,如果是返回 true。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值