shell(一)

什么是shell

  • Shell(外壳) 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言又是一种程序设计语言
  • Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

  • Shell属于内置的脚本,程序开发的效率非常高,依赖于功能强大的命令可以迅速地完成开发任务(批处理)

常见的shell种类?

在linux中有很多类型的shell,不同的shell具备不同的功能,shell还决定了脚本中函数的语法,Linux中默认的shell是/bin/bash(重点),流行的shell有ash、bash、ksh、csh、zsh等,不同的shell都有自己的特点以及用途。

shell入门

bash常见操作:

  • 常见快捷键:
    • ctrl+c   终止前台运行的程序 
      ctrl+d   退出 等价exit
      ctrl+l   清屏 
      ctrl+a   光标移到命令行的最前端          //编辑命令
      ctrl+e   光标移到命令行的后端            //编辑命令
      ctrl+u   删除光标前所有字符              //编辑命令
      ctrl+k   删除光标后所有字符              //编辑命令
      ctrl+r   搜索历史命令                   //命令需连续
  • 常见通配符:
    •   
      *:    匹配0或多个任意字符
      ?:    匹配任意单个字符
      [list]:    匹配[list]中的任意单个字符        //[abc]、[1-4]
      [!list]: 匹配除list中的任意单个字符
      {string1,string2,...}:匹配string1,string2或更多字符串
      #创建多个文件:touch {1..13}.jpg
  • $()和${}
    • $( )中放的是命令,相当于` `,例如todaydate=$(date +%Y%m%d)意思是执行date命令,返回执行结果给变量todaydate,也可以写为todaydate=`date +%Y%m%d`;
    • ${ }中放的是变量,例如echo ${PATH}取PATH变量的值并打印,也可以不加括号比如$PATH
  • bash中的引号:
    • 双引号"" :会把引号的内容当成整体来看待,允许通过$符号引用其他变量值
    • 单引号'' :会把引号的内容当成整体来看待,禁止引用其他变量值,shell中特殊符号都被视为普通字符
    • 反撇号`` :反撇号和$()一样,引号或括号里的命令会优先执行,如果存在嵌套,反撇号不能用

 

使用流程:

  • 创建.sh文件
  • 编写shell代码

    #!/bin/bash
    #脚本第一行 , #!魔法字符,指定脚本代码执行的程序。即它告诉系统这个脚本需要什么解释器来执行,也就是使用哪一种Shell

    #以下内容是对脚本的基本信息的描述
    # Name: 名字
    # Desc:描述describe
    # Path:存放路径
    # Usage:用法
    # Update:更新时间

    #下面就是脚本的具体内容
    commands
    ...

  • 执行shell脚本 (chmod +x):脚本路径;/bin/bash 脚本路径,如果脚本没有权限,可以使用第二种方式执行

 

shell进阶

变量

  • 变量分为本地变量,环境变量,全局变量
    • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。
    • 环境变量:当前进程有效,并且能够被子进程调用。
      • 查看当前用户的环境变量 //env
      • 查询当前用户的所有变量(临时变量与环境变量) //set
      • export //将当前变量变成环境变量,比如export a=1
    • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.
      • $HOME/.bashrc             当前用户的bash信息(aliase、umask等)
        $HOME/.bash_profile       当前用户的环境变量
        $HOME/.bash_logout        每个用户退出当前shell时最后读取的文件
        /etc/bashrc               使用bash shell用户全局变量
        /etc/profile              系统和每个用户的环境变量信息
        
        /etc/profile——>$HOME/.bash_profile——>$HOME/.bashrc——>/etc/bashrc——>$HOME/.bash_logout
    • 系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.
      • $#:脚本后面接的参数的个数
        $*:脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
        $@: 脚本后面所有参数,参数是独立的,也是全部输出
        $?:上一条命令执行后返回的状态,当返回状态值为0时表示执行正常,非0值表示执行异常或出错
         若退出状态值为0,表示命令运行成功
         若退出状态值为127,表示command not found
         若退出状态值为126,表示找到了该命令但无法执行(权限不够)
         若退出状态值为1&2,表示没有那个文件或目录
         
        $$:当前所在进程的进程号     echo $$   eg:kill -9 `echo $$`  = exit   退出当前会话
        $!:后台运行的最后一个进程号  (当前终端)  # gedit &
        !$    调用最后一条命令历史中的参数
        !!    调用最后一条命令历史
        $0:当前执行的进程/程序名  echo $0        
        $1~$9 位置参数变量
        ${10}~${n} 扩展位置参数变量(多位数要括起来,比如111,21,32)  第10个位置变量必须用{}大括号括起来
        
        了解$*和$@的区别:
        #!/bin/bash
        for i in "$@";do
        echo $i
        done
        
        echo "======我是分割线======="
        
        for i in "$*";do
        echo $i
        done

变量相关操作

1. 默认情况下,shell里定义的变量是不分类型的,可以给变量赋与任何类型的值;等号两边不能有空格,对于有空格的字符串做为赋值时,要用引号引起来

变量名=变量值

2. 变量的获取方式:    $变量名     ${变量名}    
[root@server ~]# A=123456789
[root@server ~]# echo $A
123456789
[root@server ~]# echo ${A:0:3}        //0代表从第1个字符开始截取,3代表截取3个字符
123

3. 取消变量:     unset  变量名(只读变量不可取消)
4. 区分大小写,同名称但大小写不同的变量名是不同的变量  
5. 变量名可以是字母或数字或下划线,但是不能以数字开头或者特殊字符
6. 命令的执行结果可以保存到变量
[root@server ~]# uname -r
2.6.32-431.el6.x86_64
[root@server ~]# kernel=`uname -r`
[root@server ~]# echo $kernel
2.6.32-431.el6.x86_64


7. 数组
数组定义:用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:
 array=(var1 var2 var3 var4)
或者
array[0]=v1
array[1]=v2
array[3]=v3

读取数组:
${array [i]}  i表示元素
使用@ 或 * 可以获取数组中的所有元素: 
获取第一个元素
echo ${user[0]}
echo ${user[*]}        获取数组里的所有元素
echo ${!array[@]}   获取数组元素的索引下标
echo ${array[@]:1:2}    访问指定的元素
[root@server ~]# echo ${user[@]}
u1 u2 u3
[root@server ~]# A=123456789
[root@server ~]# echo ${A:3:4}
4567
[root@server ~]# echo ${user[@]:1:2}
u2 u3

举例:
# for i in `echo ${user[*]}`;do echo "hello,$i";done

8. 有类型变量 declare
-i 将变量看成整数 
-r 使变量只读  readonly
-x 标记变量通过环境导出  export

[root@server shell01]# a=10
[root@server shell01]# b=20
[root@server shell01]# c=$a+$b
[root@server shell01]# echo $c
10+20
[root@server shell01]# 
[root@server shell01]# declare -i a=10
[root@server shell01]# declare -i b=20
[root@server shell01]# declare -i c=$a+$b
[root@server shell01]# echo $c
30


9. 交互式定义变量的值 read    主要用于让用户去定义变量值
-p 提示信息
-n 限制字符数 
-s 不显示
-t 超时(默认单位秒)

10. 其他变量(扩展)
1)取出一个目录下的目录和文件:dirname和 basename 
2)变量"内容"的删除和替换
一个“%”代表从右往左去掉一个/key/
两个“%%”代表从右往左最大去掉/key/
一个“#”代表从左往右去掉一个/key/
两个“##”代表从左往右最大去掉/key/

# A=/root/Desktop/shell/mem.txt 
# echo $A
/root/Desktop/shell/mem.txt
# dirname $A   取出目录
/root/Desktop/shell
# basename $A  取出文件
mem.txt
# echo ${A%/*}   从右往左去掉“/*”内容
/root/Desktop/shell
# echo ${A%%.*} 从右往左最大长度去掉.后的内容
/root/Desktop/shell/mem
# echo ${A%%.txt}  从右往左最大长度去掉.txt内容
/root/Desktop/shell/mem
# echo ${A##/*/} 从左往右最大去掉所有"/*/"
mem.txt
# echo ${A#/*/}
Desktop/shell/mem.txt

//以下扩展内容自己练习完成
 1000  url=www.taobao.com
 1001  echo ${#url}     获取变量的长度
 1008  echo ${url#*.}
 1009  echo ${url##*.}
 1011  echo ${url%.*}
 1012  echo ${url%%.*}
 
替换:/ 和 //
 1015  echo ${url/ao/AO}
 1017  echo ${url//ao/AO}   贪婪替换
 
替代: - 和 :-  +和:+
 1019  echo ${abc-123}
 1020  abc=hello
 1021  echo ${abc-444}
 1022  echo $abc
 1024  abc=
 1025  echo ${abc-222}

${变量名-新的变量值} 或者 ${变量名=新的变量值}
变量没有被赋值:会使用“新的变量值“ 替代
变量有被赋值(包括空值): 不会被替代

 1062  echo ${ABC:-123}
 1063  ABC=HELLO
 1064  echo ${ABC:-123}
 1065  ABC=
 1066  echo ${ABC:-123}

${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
变量有被赋值: 不会被替代

 1116  echo ${abc=123}
 1118  echo ${abc:=123}

[root@server ~]# unset abc
[root@server ~]# echo ${abc:+123}

[root@server ~]# abc=hello
[root@server ~]# echo ${abc:+123}
123
[root@server ~]# abc=
[root@server ~]# echo ${abc:+123}

${变量名+新的变量值}
变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
变量有被赋值: 会被替代
[root@server ~]# unset abc
[root@server ~]# echo ${abc+123}

[root@server ~]# abc=hello
[root@server ~]# echo ${abc+123}
123
[root@server ~]# abc=
[root@server ~]# echo ${abc+123}
123
${变量名:+新的变量值}
变量没有被赋值:不会使用“新的变量值“ 替代
变量有被赋值(包括空值): 会被替代

[root@server ~]# unset abc
[root@server ~]# echo ${abc?123}
-bash: abc: 123

[root@server ~]# abc=hello
[root@server ~]# echo ${abc?123}
hello
[root@server ~]# abc=
[root@server ~]# echo ${abc?123}

${变量名?新的变量值}
变量没有被赋值:提示错误信息
变量被赋值(包括空值):不会使用“新的变量值“ 替代

[root@server ~]# unset abc
[root@server ~]# echo ${abc:?123}
-bash: abc: 123
[root@server ~]# abc=hello
[root@server ~]# echo ${abc:?123}
hello
[root@server ~]# abc=
[root@server ~]# echo ${abc:?123}
-bash: abc: 123

${变量名:?新的变量值}
变量没有被赋值或者赋空值时:提示错误信息
变量被赋值:不会使用“新的变量值“ 替代

说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能

 

只读变量(了解)

#!/bin/bash
a=1 readonly a a=2 #会报错
只读变量不可删除,declare也可以

流程控制语句

#!/bin/bash
#一个条件
if condition
then
    command
    ...
fi

#两个条件
if condition
then
    command
    ...
else condition
    command
    ...
fi


#n个条件
if condition1
then
    command
    ...
elif condition2
then
    command
    ...
else
    command
    ...
fi

 

条件判断

格式1: test 条件表达式

格式2: [ 条件表达式 ]

格式3: [[ 条件表达式 ]] 支持正则 =~

 

运算符

在shell中,运算符和其他编程脚本语言一样,常见的有算数运算符、关系运算符、

逻辑运算符、字符串运算符、文件测试运算符

算数运算符

运算符    说明                 举例
+        加法                `expr $a + $b` 
- 减法 `expr $a - $b`
* 乘法 `expr $a \* $b`
/ 除法 `expr $b / $a`
% 取余 `expr $b % $a`
= 赋值 a=$b == 相等。 [ $a == $b ]
!= 不相等。 [ $a != $b ]

 

注意:

  • 条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
  • 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

关系运算符

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

运算符         说明                                                    举例
-eq        检测两个数是否相等,相等返回 true。                        [ $a -eq $b ]
-ne        检测两个数是否相等,不相等返回 true。                      [ $a -ne $b ]
-gt        检测左边的数是否大于右边的,如果是,则返回 true。           [ $a -gt $b ]
-lt        检测左边的数是否小于右边的,如果是,则返回 true。           [ $a -lt $b ] 
-ge        检测左边的数是否大于等于右边的,如果是,则返回 true。        [ $a -ge $b ] 
-le        检测左边的数是否小于等于右边的,如果是,则返回 true。        [ $a -le $b ] 

逻辑运算符

运算符    说明                                                    举例
!        非运算,表达式为 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
逻辑判断符号:
-a     &&  (and 逻辑与)
-o     ||or 逻辑或)
 !   逻辑非
[ 1 -eq 1 -a 1 -ne 0 ]
[ 1 -eq 1 -o 1 -ne 1 ]

[root@server shell01]# [ 1 -eq 0 ] && echo true || echo false
false
[root@server shell01]# [ 1 -eq 1 ] && echo true || echo false
true


优先级:
-a(&&) > -o||> !

字符串运算符

运算符    说明                                        举例
=        检测两个字符串是否相等,相等返回 true。        [ $a = $b ] 
!=        检测两个字符串是否相等,不相等返回 true。     [ $a != $b ] 
-z        检测字符串长度是否为0,为0返回 true。        [ -z $a ] 
-n        检测字符串长度是否为0,不为0返回 true。      [ -n $a ]
str        检测字符串是否为空,不为空返回 true。       [ $a ] 

文件测试运算符

文件测试运算符用于检测 Unix/Linux 文件的各种属性。

操作符          说明                                                                           举例
-b file        检测文件是否是块设备文件,如果是,则返回 true。                                     [ -b $file ] 
-c file        检测文件是否是字符设备文件,如果是,则返回 true。                                   [ -c $file ] 
-d file        检测文件是否是目录,如果是,则返回 true。                                          [ -d $file ] 
-f file        检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。              [ -f $file ] 
-g file        检测文件是否设置了 SGID 位,如果是,则返回 true。                                  [ -g $file ] 
-k file        检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。                         [ -k $file ] 
-p file        检测文件是否是有名管道,如果是,则返回 true。                                       [ -p $file ] 
-u file        检测文件是否设置了 SUID 位,如果是,则返回 true。                                   [ -u $file ] 
-r file        检测文件是否可读,如果是,则返回 true。                                            [ -r $file ] 
-w file        检测文件是否可写,如果是,则返回 true。                                            [ -w $file ] 
-x file        检测文件是否可执行,如果是,则返回 true。                                          [ -x $file ] 
-s file        检测文件是否为空(文件大小是否大于0),不为空返回 true。                              [ -s $file ] 
-e file        检测文件(包括目录)是否存在,如果是,则返回 true。                                  [ -e $file ] 

示例

示例:
数值比较:
[root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
[root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
[root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"


类C风格的数值比较:
 1159  ((1==2));echo $?
 1160  ((1<2));echo $?
 1161  ((2>=1));echo $?
 1162  ((2!=1));echo $?
 1163  ((`id -u`==0));echo $?
 1209  ((a=123));echo $a
 1210  unset a
 1211  ((a==123));echo $?
 
注意:在(( ))中,=表示赋值;==表示判断

字符串比较:
注意:双引号引起来,看作一个整体
 1196  a='hello world';b=world
 1197  [ $a = $b ];echo $?
 1198  [ "$a" = "$b" ];echo $?
 1199  [ "$a" != "$b" ];echo $?
 1200  [ "$a" !== "$b" ];echo $?        错误
 1201  [ "$a" == "$b" ];echo $?
 1202  test "$a" != "$b";echo $?

注意:= 和 == 在 [ 字符串 ] 比较中都表示判断
字符串一定要用“”

思考:[ ] 和 [[ ]] 有什么区别?

 1213  a=
 1214  test -z $a;echo $?
 1215  a=hello
 1216  test -z $a;echo $?
 1217  test -n $a;echo $?
 1217  test -n "$a";echo $?

# [ '' = $a ];echo $?
-bash: [: : unary operator expected
2
# [[ '' = $a ]];echo $?
0
[[]]:可以比较为空

1278 [ 1 -eq 0 -a 1 -ne 0 ];echo $? 1279 [ 1 -eq 0 && 1 -ne 0 ];echo $? 1280 [[ 1 -eq 0 && 1 -ne 0 ]];echo $?

 

shell中sh, exec, source, fork, ./的区别




 

 

posted @ 2020-04-21 17:22  鱼虫光  阅读(237)  评论(0编辑  收藏  举报