Linux Shell学习
1.Shell
shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁。用户的大部分工作都是通过Shell完毕的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和运行用户输入的命令。作为程序设计语言,它定义了各种变量和參数,并提供了很多在高级语言中才具有的控制结构,包含循环和分支。
2.Shell有两种运行命令的方式:
- 交互式(Interactive):解释运行用户的命令,用户输入一条命令,Shell就解释运行一条。
- 批处理(Batch):用户事先写一个Shell脚本(Script),当中有非常多条命令。让Shell一次把这些命令运行完,而不必一条一条地敲命令。
3.bash全然兼容sh。也就是说,用sh写的脚本能够不加改动的在bash中运行。
4.Shell支持自己定义变量。
定义变量时,变量名不加美元符号($),如:
- variableName="value"
- 中间不能有空格,能够使用下划线(_)。
- 不能使用标点符号。
- 不能使用bash里的keyword(可用help命令查看保留keyword)。
5.使用一个定义过的变量,仅仅要在变量名前面加美元符号($)就可以,如:
- your_name="mozhiyan"
- echo $your_name
- echo ${your_name}}
- for skill in Ada Coffe Action Java
- do
- echo "I am good at ${skill}Script"
- done
推荐给全部变量加上花括号,这是个好的编程习惯。
6.仅仅读变量
使用 readonly 命令能够将变量定义为仅仅读变量,仅仅读变量的值不能被改变。以下的样例尝试更改仅仅读变量,结果报错:
- #!/bin/bash
- myUrl="http://see.xidian.edu.cn/cpp/shell/"
- readonly myUrl
- myUrl="http://see.xidian.edu.cn/cpp/danpianji/"
/bin/sh: NAME: This variable is read only.
7.删除变量
使用 unset 命令能够删除变量。语法:
- unset variable_name
8.算术运算符
- if [ $a == $b ]
- then
- echo "a is equal to b"
- 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里没有多行凝视。仅仅能每一行加一个#号。
假设在开发过程中,遇到大段的代码须要暂时凝视起来。过一会儿又取消凝视,怎么办呢?每一行加个#符号太费力了,能够把这一段要凝视的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会运行,达到了和凝视一样的效果。
sh里没有多行凝视。仅仅能每一行加一个#号。
仅仅能像这样:
- #--------------------------------------------
- # 这是一个自己主动打ipa的脚本,基于webfrogs的ipa-build书写:
- # https://github.com/webfrogs/xcode_shell/blob/master/ipa-build
- # 功能:自己主动为etao ios app打包。产出物为14个渠道的ipa包
- # 特色:全自己主动打包,不须要输入不论什么參数
- #--------------------------------------------
14.获取字符串长度
- string="abcd"
- echo ${#string} #输出 4
提取字符串
- string="alibaba is a great company"
- echo ${string:1:4} #输出liba
查找字符串
- string="alibaba is a great company"
- echo `expr index "$string" is`#输出3(i是第3个字符)
15.定义数组
在Shell中。用括号来表示数组,数组元素用“空格”符号切割开。定义数组的一般形式为:
array_name=(value1 ... valuen)
比如:
- array_name=(value0 value1 value2 value3)
还能够单独定义数组的各个分量:
- array_name[0]=value0
- array_name[1]=value1
- array_name[2]=value2
读取数组元素值的一般格式是:
${array_name[index]}
比如:
- valuen=${array_name[2]}
- ${array_name[*]}
- ${array_name[@]}
- #!/bin/sh
- NAME[0]="Zara"
- NAME[1]="Qadir"
- NAME[2]="Mahnaz"
- NAME[3]="Ayan"
- NAME[4]="Daisy"
- echo "First Method: ${NAME[*]}"
- echo "Second Method: ${NAME[@]}"
$./test.sh
First Method: Zara Qadir Mahnaz Ayan Daisy
Second Method: Zara Qadir Mahnaz Ayan Daisy
获取数组长度的方法与获取字符串长度的方法同样,比如:
- length=${#array_name[@]}
- # 或者
- length=${#array_name[*]}
- # 取得数组单个元素的长度
- lengthn=${#array_name[n]}
16.printf 命令用于格式化输出
如同 echo 命令,printf 命令也能够输出简单的字符串:
- $printf "Hello, Shell\n"
- Hello, Shell
- $
printf 命令的语法:
printf format-string [arguments...]
format-string 为格式控制字符串,arguments 为參数列表。与C语言printf()函数的不同:
注意。依据POSIX标准,浮点格式%e、%E、%f、%g与%G是“不须要被支持”。这是由于awk支持浮点预算,且有它自己的printf语句。
- printf 命令不用加括号
- format-string 能够没有引號,但最好加上,单引號双引號均可。
- 參数多于格式控制符(%)时,format-string 能够重用。能够将全部參数都转换。
- arguments 使用空格分隔,不用逗号。
- # format-string为双引號
- $ printf "%d %s\n" 1 "abc"
- 1 abc
- # 单引號与双引號效果一样
- $ printf '%d %s\n' 1 "abc"
- 1 abc
- # 没有引號也能够输出
- $ printf %s abcdef
- abcdef
- # 格式仅仅指定了一个參数。但多出的參数仍然会依照该格式输出,format-string 被重用
- $ printf %s abc def
- abcdef
- $ printf "%s\n" abc def
- abc
- def
- $ printf "%s %s %s\n" a b c d e f g h i j
- a b c
- d e f
- g h i
- j
- # 假设没有 arguments,那么 %s 用NULL取代。%d 用 0 取代
- $ printf "%s and %d \n"
- and 0
- # 假设以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
- $ printf "The first program always prints'%s,%d\n'" Hello Shell
- -bash: printf: Shell: invalid number
- The first program always prints 'Hello,0'
- $
这样Shell程序中须要将浮点数值进行格式化的打印时,可使用小型的awk程序实现。然而,内建于bash、ksh93和zsh中的printf命令都支持浮点格式。
17.for循环
for循环一般格式为:
执行结果:
顺序输出字符串中的字符:
执行结果:
for 变量 in 列表
do
command1
command2
...
commandN
done
列表是一组值(数字、字符串等)组成的序列,每一个值通过空格分隔。每循环一次。就将列表中的下一个值赋给变量。
in 列表是可选的,假设不用它。for 循环使用命令行的位置參数。
比如,顺序输出当前列表中的数字:
- for loop in 1 2 3 4 5
- do
- echo "The value is: $loop"
- done
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
顺序输出字符串中的字符:
- for str in 'This is a string'
- do
- echo $str
- done
This is a string
假设不加引號则输出:This
is
a
string
显示主文件夹下以 .bash 开头的文件:
执行结果:
显示主文件夹下以 .bash 开头的文件:
- #!/bin/bash
- for FILE in $HOME/.bash*
- do
- echo $FILE
- done
/root/.bash_history
/root/.bash_logout
/root/.bashrc
18.函数
函数能够让我们将一个复杂功能划分成若干模块。让程序结构更加清晰,代码反复利用率更高。
Shell 函数返回值仅仅能是整数,一般用来表示函数运行成功与否。0表示成功,其它值表示失败。
像其它编程语言一样。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语句的函数:
执行结果:
假设你希望直接从终端调用函数。能够将函数定义在主文件夹下的 .profile 文件。这样每次登录后,在命令提示符后面输入函数名字就能够马上调用。
- #!/bin/bash
- funWithReturn(){
- echo "The function is to get the sum of two numbers..."
- echo -n "Input first number: "
- read aNum
- echo -n "Input another number: "
- read anotherNum
- echo "The two numbers are $aNum and $anotherNum !"
- return $(($aNum+$anotherNum))
- }
- funWithReturn
- # Capture value returnd by last command
- ret=$?
- 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表示第二个參数...
带參数的函数演示样例:
执行脚本:
带參数的函数演示样例:
- #!/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 !" # $1的值 和 0
- 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
#!/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}来获取參数。