首页 > 代码库 > Linux Shell学习

Linux Shell学习

1.Shell

shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁。用户的大部分工作都是通过Shell完毕的。

Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和运行用户输入的命令。作为程序设计语言,它定义了各种变量和參数,并提供了很多在高级语言中才具有的控制结构,包含循环和分支。


2.Shell有两种运行命令的方式:

  • 交互式(Interactive):解释运行用户的命令,用户输入一条命令,Shell就解释运行一条。
  • 批处理(Batch):用户事先写一个Shell脚本(Script),当中有非常多条命令。让Shell一次把这些命令运行完,而不必一条一条地敲命令。
Shell脚本和编程语言非常相似,也有变量和流程控制语句,但Shell脚本是解释运行的,不须要编译,Shell程序从脚本中一行一行读取并运行这些命令。相当于一个用户把脚本中的命令一行一行敲到Shell提示符下运行。


3.bash全然兼容sh。也就是说,用sh写的脚本能够不加改动的在bash中运行。

4.Shell支持自己定义变量。

定义变量时,变量名不加美元符号($),如:

  1. variableName="value"
注意,变量名和等号之间不能有空格(两側都不能够有空格)。这可能和你熟悉的全部编程语言都不一样。同一时候,变量名的命名须遵循例如以下规则:
  • 间不能有空格,能够使用下划线(_)。

  • 不能使用标点符号。
  • 不能使用bash里的keyword(可用help命令查看保留keyword)。 

5.使用一个定义过的变量,仅仅要在变量名前面加美元符号($)就可以,如:


  1. your_name="mozhiyan"
  2. echo $your_name
  3. echo ${your_name}}
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。比方以下这样的情况:

  1. for skill in Ada Coffe Action Java
  2. do
  3. echo "I am good at ${skill}Script"
  4. done
假设不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量(其值为空),代码运行结果就不是我们期望的样子了。

推荐给全部变量加上花括号,这是个好的编程习惯。

6.仅仅读变量

使用 readonly 命令能够将变量定义为仅仅读变量,仅仅读变量的值不能被改变。

以下的样例尝试更改仅仅读变量,结果报错:
  1. #!/bin/bash
  2.  
  3. myUrl="http://see.xidian.edu.cn/cpp/shell/"
  4. readonly myUrl
  5. myUrl="http://see.xidian.edu.cn/cpp/danpianji/"
执行脚本,结果例如以下:
/bin/sh: NAME: This variable is read only.

7.删除变量

使用 unset 命令能够删除变量。语法:
  1. unset variable_name
变量被删除后不能再次使用;unset 命令不能删除仅仅读变量。

8.算术运算符

  1. if [ $a == $b ]
  2. then
  3. echo "a is equal to b"
  4. fi
注意:条件表达式要放在方括号之间,而且要有空格,比如 [$a==$b] 是错误的,必须写成 [ $a == $b ]。

乘号(*)前边必须加反斜杠(\)才干实现乘法运算
算术运算符列表
运算符 说明 举例
+ 加法 `expr $a + $b` 结果为 30。

- 减法 `expr $a - $b` 结果为 10。
* 乘法 `expr $a \* $b` 结果为  200

/ 除法 `expr $b / $a` 结果为 2。

% 取余 `expr $b % $a` 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等。用于比較两个数字,同样则返回 true。 [ $a == $b ] 返回 false。
!= 不相等。

用于比較两个数字。不同样则返回 true。

[ $a != $b ] 返回 true。



9.关系运算符

关系运算符仅仅支持数字,不支持字符串,除非字符串的值是数字。

关系运算符列表
运算符 说明 举例
-eq 检測两个数是否相等。相等返回 true。 [ $a -eq $b ] 返回 true。
-ne 检測两个数是否相等。不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检測左边的数是否大于右边的,假设是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检測左边的数是否小于右边的,假设是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检測左边的数是否大等于右边的,假设是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检測左边的数是否小于等于右边的,假设是,则返回 true。 [ $a -le $b ] 返回 true。



10.布尔运算符

布尔运算符列表
运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。

-o 或运算,有一个表达式为 true 则返回 true。

[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算。两个表达式都为 true 才返回 true。

[ $a -lt 20 -a $b -gt 100 ] 返回 false。


11.字符串运算符

字符串运算符列表
运算符 说明 举例
= 检測两个字符串是否相等,相等返回 true。

[ $a = $b ] 返回 false。
!= 检測两个字符串是否相等,不相等返回 true。

[ $a != $b ] 返回 true。

-z 检測字符串长度是否为0。为0返回 true。 [ -z $a ] 返回 false。
-n 检測字符串长度是否为0,不为0返回 true。 [ -z $a ] 返回 true。

str 检測字符串是否为空,不为空返回 true。 [ $a ] 返回 true。


12.文件測试运算符

文件測试运算符列表
操作符 说明 举例
-b file 检測文件是否是块设备文件。假设是,则返回 true。 [ -b $file ] 返回 false。

-c file 检測文件是否是字符设备文件。假设是,则返回 true。 [ -b $file ] 返回 false。
-d file 检測文件是否是文件夹。假设是,则返回 true。 [ -d $file ] 返回 false。

-f file 检測文件是否是普通文件(既不是文件夹,也不是设备文件),假设是,则返回 true。

[ -f $file ] 返回 true。

-g file 检測文件是否设置了 SGID 位。假设是。则返回 true。 [ -g $file ] 返回 false。
-k file 检測文件是否设置了粘着位(Sticky Bit),假设是。则返回 true。 [ -k $file ] 返回 false。
-p file 检測文件是否是具名管道,假设是,则返回 true。 [ -p $file ] 返回 false。

-u file 检測文件是否设置了 SUID 位,假设是,则返回 true。

[ -u $file ] 返回 false。
-r file 检測文件是否可读,假设是。则返回 true。 [ -r $file ] 返回 true。

-w file 检測文件是否可写,假设是,则返回 true。 [ -w $file ] 返回 true。
-x file 检測文件是否可运行,假设是,则返回 true。

[ -x $file ] 返回 true。
-s file 检測文件是否为空(文件大小是否大于0),不为空返回 true。

[ -s $file ] 返回 true。
-e file 检測文件(包含文件夹)是否存在,假设是。则返回 true。 [ -e $file ] 返回 true。


13.凝视

以“#”开头的行就是凝视,会被解释器忽略。

sh里没有多行凝视。仅仅能每一行加一个#号

仅仅能像这样:

  1. #--------------------------------------------
  2. # 这是一个自己主动打ipa的脚本,基于webfrogs的ipa-build书写:
  3. # https://github.com/webfrogs/xcode_shell/blob/master/ipa-build
  4.  
  5. # 功能:自己主动为etao ios app打包。产出物为14个渠道的ipa包
  6. # 特色:全自己主动打包,不须要输入不论什么參数
  7. #--------------------------------------------
假设在开发过程中,遇到大段的代码须要暂时凝视起来。过一会儿又取消凝视,怎么办呢?每一行加个#符号太费力了,能够把这一段要凝视的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会运行,达到了和凝视一样的效果。

14.获取字符串长度

  1. string="abcd"
  2. echo ${#string} #输出 4

提取字符串

  1. string="alibaba is a great company"
  2. echo ${string:1:4} #输出liba

查找字符串

  1. string="alibaba is a great company"
  2. echo `expr index "$string" is`#输出3(i是第3个字符)

15.定义数组

在Shell中。用括号来表示数组,数组元素用“空格”符号切割开

定义数组的一般形式为:
    array_name=(value1 ... valuen)
比如:

  1. array_name=(value0 value1 value2 value3)

还能够单独定义数组的各个分量:

  1. array_name[0]=value0
  2. array_name[1]=value1
  3. array_name[2]=value2
能够不使用连续的下标。并且下标的范围没有限制。 

读取数组元素值的一般格式是:

    ${array_name[index]}
比如:

  1. valuen=${array_name[2]}
使用@ 或 * 能够获取数组中的全部元素,比如:

  1. ${array_name[*]}
  2. ${array_name[@]}
举个样例:
  1. #!/bin/sh
  2.  
  3. NAME[0]="Zara"
  4. NAME[1]="Qadir"
  5. NAME[2]="Mahnaz"
  6. NAME[3]="Ayan"
  7. NAME[4]="Daisy"
  8. echo "First Method: ${NAME[*]}"
  9. echo "Second Method: ${NAME[@]}"
执行脚本。输出:
$./test.sh
First Method: Zara Qadir Mahnaz Ayan Daisy
Second Method: Zara Qadir Mahnaz Ayan Daisy

获取数组长度的方法与获取字符串长度的方法同样,比如: 
# 取得数组元素的个数
  1. length=${#array_name[@]}
  2. # 或者
  3. length=${#array_name[*]}
  4. # 取得数组单个元素的长度
  5. lengthn=${#array_name[n]}

16.printf 命令用于格式化输出

如同 echo 命令,printf 命令也能够输出简单的字符串:
  1. $printf "Hello, Shell\n"
  2. Hello, Shell
  3. $
printf 不像 echo 那样会自己主动换行,必须显式加入换行符(\n)。



printf 命令的语法:

printf  format-string  [arguments...]
format-string 为格式控制字符串,arguments 为參数列表。
与C语言printf()函数的不同:
  • printf 命令不用加括号
  • format-string 能够没有引號,但最好加上,单引號双引號均可。
  • 參数多于格式控制符(%)时,format-string 能够重用。能够将全部參数都转换。
  • arguments 使用空格分隔,不用逗号。

请看以下的样例:
  1. # format-string为双引號
  2. $ printf "%d %s\n" 1 "abc"
  3. 1 abc
  4. # 单引號与双引號效果一样
  5. $ printf ‘%d %s\n 1 "abc"
  6. 1 abc
  7. # 没有引號也能够输出
  8. $ printf %s abcdef
  9. abcdef
  10. # 格式仅仅指定了一个參数。但多出的參数仍然会依照该格式输出,format-string 被重用
  11. $ printf %s abc def
  12. abcdef
  13. $ printf "%s\n" abc def
  14. abc
  15. def
  16. $ printf "%s %s %s\n" a b c d e f g h i j
  17. a b c
  18. d e f
  19. g h i
  20. j
  21. # 假设没有 arguments,那么 %s 用NULL取代。%d 用 0 取代
  22. $ printf "%s and %d \n"
  23. and 0
  24. # 假设以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
  25. $ printf "The first program always prints‘%s,%d\n‘" Hello Shell
  26. -bash: printf: Shell: invalid number
  27. The first program always prints ‘Hello,0‘
  28. $
注意。依据POSIX标准,浮点格式%e、%E、%f、%g与%G是“不须要被支持”。这是由于awk支持浮点预算,且有它自己的printf语句。

这样Shell程序中须要将浮点数值进行格式化的打印时,可使用小型的awk程序实现。然而,内建于bash、ksh93和zsh中的printf命令都支持浮点格式。


17.for循环

for循环一般格式为:
for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done
列表是一组值(数字、字符串等)组成的序列,每一个值通过空格分隔。每循环一次。就将列表中的下一个值赋给变量。



in 列表是可选的,假设不用它。for 循环使用命令行的位置參数。



比如,顺序输出当前列表中的数字:

  1. for loop in 1 2 3 4 5
  2. do
  3. echo "The value is: $loop"
  4. done
执行结果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5

顺序输出字符串中的字符:
  1. for str in ‘This is a string‘
  2. do
  3. echo $str
  4. done
执行结果:
This is a string
假设不加引號则输出:
This
is
a
string
显示主文件夹下以 .bash 开头的文件:
  1. #!/bin/bash
  2.  
  3. for FILE in $HOME/.bash*
  4. do
  5. echo $FILE
  6. done
执行结果:
/root/.bash_history
/root/.bash_logout
/root/.bashrc

18.函数

函数能够让我们将一个复杂功能划分成若干模块。让程序结构更加清晰,代码反复利用率更高。

像其它编程语言一样。Shell 也支持函数。

Shell 函数必须先定义后使用。

Shell 函数的定义格式例如以下:

function_name () {
    list of commands
    [ return value ]
}
假设你愿意,也能够在函数名前加上keyword function:
function function_name () {
    list of commands
    [ return value ]
}
函数返回值。能够显式添加return语句;假设不加。会将最后一条命令执行结果作为返回值。

Shell 函数返回值仅仅能是整数,一般用来表示函数运行成功与否。0表示成功,其它值表示失败。

假设 return 其它数据,比方一个字符串。往往会得到错误提示:“numeric argument required”。



假设一定要让函数返回字符串,那么能够先定义一个变量,用来接收函数的计算结果。脚本在须要的时候訪问这个变量来获得函数返回值。
调用函数仅仅须要给出函数名。不须要加括号。


看一个带有return语句的函数:
  1. #!/bin/bash
  2. funWithReturn(){
  3. echo "The function is to get the sum of two numbers..."
  4. echo -n "Input first number: "
  5. read aNum
  6. echo -n "Input another number: "
  7. read anotherNum
  8. echo "The two numbers are $aNum and $anotherNum !"
  9. return $(($aNum+$anotherNum))
  10. }
  11. funWithReturn
  12. # Capture value returnd by last command
  13. ret=$?
  14. echo "The sum of two numbers is $ret !"
执行结果:
The function is to get the sum of two numbers...
Input first number: 25
Input another number: 50
The two numbers are 25 and 50 !
The sum of two numbers is 75 !
函数返回值在调用该函数后通过 $? 来获得
假设你希望直接从终端调用函数。能够将函数定义在主文件夹下的 .profile 文件。这样每次登录后,在命令提示符后面输入函数名字就能够马上调用

19.函数调用

在Shell中,调用函数时能够向其传递參数。在函数体内部,通过 $n 的形式来获取參数的值,比如。$1表示第一个參数,$2表示第二个參数...

带參数的函数演示样例:
复制纯文本新窗体
  1. #!/bin/bash
  2. funWithParam(){
  3. echo "The value of the first parameter is $1 !"
  4. echo "The value of the second parameter is $2 !"
  5. echo "The value of the tenth parameter is $10 !" # $1的值 和 0
  6. echo "The value of the tenth parameter is ${10} !"
  7. echo "The value of the eleventh parameter is ${11} !"
  8. echo "The amount of the parameters is $# !" # 參数个数
  9. echo "The string of the parameters is $* !" # 传递给函数的全部參数
  10. }
  11. funWithParam 1 2 3 4 5 6 7 8 9 34 73
#!/bin/bash
funWithParam(){
    echo "The value of the first parameter is $1 !"
    echo "The value of the second parameter is $2 !"
    echo "The value of the tenth parameter is $10 !"
    echo "The value of the tenth parameter is ${10} !"
    echo "The value of the eleventh parameter is ${11} !"
    echo "The amount of the parameters is $# !"  # 參数个数
    echo "The string of the parameters is $* !"  # 传递给函数的全部參数
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
执行脚本:
The value of the first parameter is 1 !
The value of the second parameter is 2 !
The value of the tenth parameter is 10 ! 
The value of the tenth parameter is 34 !
The value of the eleventh parameter is 73 !
The amount of the parameters is 11 !
The string of the parameters is 1 2 3 4 5 6 7 8 9 34 73 !"
注意,$10 不能获取第十个參数,获取第十个參数须要${10}。当n>=10时,须要使用${n}来获取參数。


Linux Shell学习