Shell

Bash 基础特性及shell编程基础

2016-03-07  本文已影响740人  魏镇坪

Bash内置基本变量

  1. PWD : 显示当前的工作目录
  2. OLDPWD : 显示上一次的工作目录
  3. ~:用户家目录
  4. - : 使用cd -命令可以在上一次工作目录和当前工作目录中来回切换
  5. HISTSIZE : 显示shell中历史命令保留数量
  6. HISTFILE : 显示历史命令文件存放路径
  7. HISTFILESIZE : 显示历史命令文件存放命令数量
  8. HISTCONTROL : 显示历史命令记录方式
    • ignoredups : 让历史命令保存方式为『不记录连续重复命令』
    • ignorespace: 让历史命令保存方式为「不记录以空格开头的命令」
    • ignoreboth : 以上两个皆有
  9. !# : 代表执行历史记录中#号命令
  10. !! : 执行上一次历史命令
  11. Esc,. : 提取上一次命令最后一个参数
  12. !$ : 提取上一次命令最后一个参数
  13. PATH : 环境变量
  14. $? : 上一次命令的执行状态结果
  15. SHELL : 当前shell
  16. home : 家目录路径
  17. UID : 用户的UID
  18. GID : 用户的GID
  19. USER: 用户名

bash特性之命令行展开

  1. ~ : 自动展开为用户家目录
  2. {} :中间以多个" , "号为分隔,依次展开为多个数量

bash特性之执行状态结果

  1. 成功 == 0
  2. 失败 == 1-255

bash特性之命令结果引用

  1. `COMMAND`
  2. $(COMMAND)

bash特性之引用

  1. 转义:用反斜杠在需要转义的字符前,表示这个字符需要看作一个普通字符
  2. 强引用:使用” ` “把所有内容都引起来,``号中的所有内容都看作为普通字符,除了引号自身,所以不要在``号内再加``号
  3. 弱引用:使用” “把内容都引起来,除了引号自身,把大部分字符都看作普通字符,例外的有 ,$ , ` ,三个特殊字符

bash特性之元字符

  1. * : 任意长度的任意字符
  2. ? : 单个字符
  3. [] : 指定范围内的任意字符
  4. [^] : 指定范围外的任意字符
    • 特殊格式
      • [a-z]:任意字母(glob中不分大小写)
      • [0-9]:任意一个数字
      • [a-z0-9]:任意一个数字和字母
      • [:alpha:] :大写及字母
      • [:upper:] :大写字母
      • [:lower:] :小写字母
      • [:digit:] :数字
      • [:alnum:] :数字和字母
      • [:space:] :空白(包含空格和制表格)
      • [:punct:]:标点符号

bash特性之hash

缓存之前命令查找的结果,就叫命令hash,也叫命令缓存,可以使用hash命令查看其缓存的命令的完事路径及命中的次数。

===============

shell编程基础

shell编程之变量

什么是变量?
内存空间地址+数据,数据是放在内存中,即也叫有名称的内存地址
变量的值的类型,决定了存储格式、表示的数据范围、参与的运算
变量赋值
`name=VALUE`
bash对变量的机制
  1. 所有都看作字符型
  2. 不支持浮点数据,需借用外部机制
  3. 变量无需事先申明,相当于,赋值和申明同时实现
程序中变量引用的机制
把变量名出现的位置,直接替换为其所指向的内存空间中的数据
变量的命名规范
  1. 不能以数字开头,只能包含数字、字母、下划线
  2. 变量名要做到见名知义
  3. 不能使用程序语言的保留字(if else where等)
变量的引用
  1. ${var_name}
  2. $var_name
变量的类型
  1. 本地变量:作用范围仅为当前shell;
  2. 环境变量:作用范围当前进程和其子进程
  3. 局部变量:作用范围为某片代码片;
  4. 特殊变量:shell内置的,有特殊功用
    • 0 = 成功
    • 1-255 = 失败
各变量的赋值、引用 、查看、删除
本地变量
环境变量
只读变量的定义
增强型变量赋值
变量做某种运算后存至变量中

=============

bash之切片

基于字符串切片

Usage: ${var:offset: length}

例:
    [root@localhost ~]#mypath="/etc/sysconfig/network-scripts/"    #定义一个变量,等会切这个变量
    [root@localhost ~]# echo ${mypath:5}       #偏移5个字符显示
    sysconfig/network-scripts/
    [root@localhost ~]# echo ${mypath:10}     #偏移10个字符显示
    nfig/network-scripts/
    [root@localhost ~]# echo ${mypath:5:5}    #偏移5个字符,取5个字符 
    sysco   
    
    取出字符串的最后几个字符:${var: -length}
        注意:-length之前有空白字符;
    [root@localhost ~]# echo ${mypath: -10}
    k-scripts/
基于模式取子串
示例:
    [root@localhost ~]#mypath="/etc/sysconfig/network-scripts"
    [root@localhost ~]# echo ${mypath#*/}
    etc/sysconfig/network-scripts
    
    [root@localhost ~]#mypath="/etc/sysconfig/network-scripts"
    [root@localhost ~]# echo ${mypath##*/}
    network-scripts
    
    [root@localhost ~]#mypath="/etc/sysconfig/network-scripts"
    [root@localhost ~]# echo ${mypath%c*}
    /etc/sysconfig/network-s
    [root@localhost ~]# echo ${mypath%%c*}
    /et
基于字串查找替换
示例:
    [root@localhost ~]#url="http://www.baidu.com:80"
    [root@localhost ~]# echo ${url/www/WWW}
    http://WWW.baidu.com:80
    [root@localhost ~]# echo ${url/w/W}
    http://Www.baidu.com:80
    
    [root@localhost ~]# echo ${url//w/W}
    http://WWW.baidu.com:80
    
    [root@localhost ~]# userinfo="root:x:0:0:rootuser:/root:/bin/bash"
    [root@localhost ~]# echo ${userinfo/#root/ROOT}
    ROOT:x:0:0:root user:/root:/bin/bash
    
    [root@localhost ~]# userinfo="root:x:0:0:rootuser:/root:/bin/root"
    [root@localhost ~]# echo ${userinfo/%root/ROOT}
    root:x:0:0:root user:/root:/bin/ROOT
基于字串查找删除
示例:
[root@localhost ~]# userinfo="root:x:0:0:rootuser:/root:/bin/root"
[root@localhost ~]# echo ${userinfo/root}
:x:0:0:root user:/root:/bin/root
[root@localhost ~]# echo ${userinfo//root}
:x:0:0: user:/:/bin/
[root@localhost ~]# echo ${userinfo/#root}
:x:0:0:root user:/root:/bin/root
[root@localhost ~]# echo ${userinfo/%root}
root:x:0:0:root user:/root:/bin/
基于字符串大小写转换
示例
[root@localhost ~]# echo $userinfo
root:x:0:0:root user:/root:/bin/root
[root@localhost ~]# myinfo=${userinfo^^}
[root@localhost ~]# echo $myinfo
ROOT:X:0:0:ROOT USER:/ROOT:/BIN/ROOT
[root@localhost ~]# echo ${myinfo,,}
root:x:0:0:root user:/root:/bin/root

空变量判断赋值

===============

bash多命令执行

  1. 无逻辑关系的

    • COMMAND1;COMMAND2;COMMAND3...
  2. 有逻辑关系的

    • 逻辑的运算结果状态:

      • (True ,1
      • (False ,0
    • 与运算(乘法)

      • 1&&1=1
      • 1&&0=0
      • 0&&1=0
      • 0&&0=0
        • 只有两个都为真,结果才为真,否则为假(遵守短路法则)
    • 或运算 :加法

      • 1 || 0 = 1
      • 1 || 1 = 1
      • 0 || 1 = 1
      • 0 || 0 = 0
        • 只要一个为真,即为真,(类似电路并链)
    • 非:取反

      • ! 1 = 0
      • ! 0 = 1
    • 异或:判断是否不同

      • 不同者为真,相同者为零假
短路法则:
#COMMAND1 && COMMAND2 : 
    COMMAND1为『假』,COMMAND2不会再执行,
    COMMAND1为『真』,COMMAND2必须执行
#COMMAND1 || COMMAND2
    COMMAND1为『真』;COMMAND2不会执行
    COMMAND1为『假』;COMMAND2必须执行
    例:# id $username || useradd $username

bash的配置文件

1、bash配置文件的分类
2、profile、bashrc类的功用
3、登录式shell、非登录shell读取配置文件的顺序
  1. 登录式shell读取顺序
    • /etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
  2. 非登录式shell读取顺序
    • ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
4、让定义的配置文件立即生效
注意: 需要定义全局的别名,需修改/etc/bashrc文件

bash之算术运算

  1. let命令

    • let SUM=$num1+$num2
    • echo $SUM
  2. 算术运算表达式一:

    • echo $[ $num1 + $num2 ]
  3. 算术运算表达式二:

    • echo $(($num1 + $num2))
  4. 算术运算表达式三:

    • expr $num1 + $num2
  5. bash的运算符

    • + - * / ** %
注意:乘法符号在有些场景中使用需要加转义符

Bash之条件测试:

判断某需求是否满足,需要由测试机制来实现

1. 使用执行命令,并利用命令状态返回值来判断

2. 测试表达式格式

bash的测试类型:

  1. 数据测试
    • 数值比较
      • -eq : 是否等;[ $nu1 -eq $num2 ]
      • -ne : 是否不等于;
      • -gt : 是否大于
      • -ge : 大于等于
      • -lt : 是否小于
      • -le : 是否小于等于
        • 注意:可以使用[],[[ ]],建立使用[]
    • 字符串测试 : 1、字符串要加引号引用 ;2、做比较时使用双中括号[[ ]]
      • == :是否等于
      • > : 是否大于,此处也要使用双中括号
      • < : 是否小于,此处也要使用双中括号
      • != :是否不等于
      • =~ :左侧的字符串是否能被右侧的pattern所匹配,匹配为一部分,不是精确匹配
      • -z “STRING” : 判断指定的字串是否为空,空则为真,不空则假
      • -n “string” :判断指定的字串是否不空,空则为假,不空则真
        • 注意:字符串与变量比较时,最好能在变量上加” ”引起来,在字符串比较的时候, 最好能使用双中括号,建议使用[[ ]] ,做等值比较时,必须要在等号前后空格,如果引用是变量,也是需要加空格,变量名可以不用引号引起来
  2. 文件测试
    • 存在性测试:
      • -a FILE
      • -e FILE
        • 文件的存在性测试,存在则为真,否则则为假
    • 存在性及文件类型
      • -b FILE : 是否存在,并且为块设备文件
      • -c FILE : 是否存在,并且为字符设备文件
      • -d FILE : 是否存在,并且为目录文件
      • -f FILE : 是否存在, 并且为普通文件
      • -h FILE 或者 -L FILE : 是否存在并且为符号连接文件
      • -p FILE : 是否存在, 且为命名管道文件
      • -S FILE :是否存在,且为套接字文件
  3. 文件权限测试
    • -r FILE : 是否存在,并且可读,对当前用户可读
    • -w FILE : 是否存在, 并且可写
    • -x FILE : 是否存在, 并且可执行
  4. 特殊权限测试
    • -g FILE : 是否存在, 并且拥有SGID权限
    • -u FILE : 是否存在,并且拥有SUID权限
    • -k FILE : 是否存在, 且拥有sticky权限
  5. 文件是否有内容
    • -s FILE :是否存在,并且是否有内容
  6. 时间戳测试
    • -N FILE : 文件自从上一次读取操作后,是否被修改过
  7. 从属关系测试:
    • -O FILE : 当前用户是否为文件的属主
    • -G FILE : 当前用户是否属于文件的属组
  8. 双目测试(文件新旧对比)
    • FILE1 -ef FILE2 : FILE1 与FILE2是否为指向同一个文件系统上的相同的inode的硬连接
    • FILE1 -nt FILE2 : FILE1是否新于FILE2
    • FILE1 -ot FILE2 : FILE1是否旧于FILE2
  9. 组合测试条件
    • 逻辑运算:
      • 第一种:
        • COMMAND1 && COMMAND2
        • COMMAND1 || COMMAND2
        • !COMMAND
          • 例:[ -O FILE ] && [ -r FILE] :是否可读并且为属主
      • 第二种:
        • [ expression1 -a expression2 ]
        • [ expression1 -o expression2 ]
        • ![ expression1 ]
          • 例: [ -O FILE -a -x FILE ] : 是否是属主并且有执行权限
注意:-a -o 只能在[]中使用,如果需要在双括号中使用逻辑换算,需要使用 && || 来代替

Bash脚本之状态返回值:

bash编程之向脚本传递参数

  1. 位置参数变量
    • 例:myscript.sh argu1 argu2
  2. 脚本中引用方式:
    • $1,$2…….${10},${11},….
  3. 位置参数变量轮替
    • shift : 把引用过的参数T掉,在脚本中永远只使用$1引用下一个
      • 例: shift 2 : 踢两个,这样就可以在脚本中永远以$1和$2来引用后面的参数

bash编程之特殊变量

bash编程之语句类型

  1. 顺序执行:逐条运行
  2. 选择执行:
    • 两个或者以上的分支:满足条件时只会执行其中一个满足条件的分支
  3. 循环执行:
    • 某代码片断(循环体)要执行0、1或多个来回

脚本之语法错误检查

脚本之用户交互的实现

  1. read [option]...[name...]
    • -p PROMPT: 直接提示输入信息,保存至变量
    • -t TIMEOUT : 超时设置,默认秒为单位

1、 选择执行:

  1. 单分支的if语句
     if 测试条件;then
         代码分支
     fi 
    
  2. 双分支的if语句
     if 测试条件;then
         条件为真时执行的分支
     else
         条件为假时执行的分支
     fi
    
  3. 多分支的if语句
     if 测试条件;then
         条件为真时执行
     elif
         条件为真时执行
     else
         条件为假是执行
     fi
    

2、循环执行

  1. for循环语句
     for VAR in LIST;do
         循环体
     done
    
进入条件:只要列表有可用元素,即可进入循环
退出条件:列表中的元素遍历完成后,即退出循环
列表的生成方式:
  1. while循环语句
     while CONDITION1;do
         循环体
         循环控制变量修正表达式
     done
    
条件进入:CONDITION测试为真
条件退出:CONDITION测试为假
  1. until循环语句
     until CONDITION;do
         循环体
         循环控制变量修正表达式
     done
    
条件进入:CONDITION测试为假
条件退出:CONDITION测试为真

在循环中控制循环的方法

1、continue
示例 : 求100以内的所有偶数之和
    #!/bin/bash
            declare  -i evensum=0
            declare -i i=0
            while [ $i -le 100 ];do
                let i++
                if [ $[$i%2] -eq 1];then
                    continue
                fi
                let evensum+=$i
            done    
2、break
示例:100以内所有奇数之和
    #!/bin/bash
    declare  -i evensum=0
    declare -i i=1
    while true;do
        let $oddsum+=$i
        let i+=2
        if [ $i -gt 100 ];then
            break
        fi
    done
while的特殊用法之遍历文件的行
while read VARIABLE;do
    循环休
done < /path/form/somefile
for循环的特殊用法
for ((控制变量初始化;条件判断表达式;控制变量的修正语句));do
    循环体
done
控制变量初始化:仅在循环代码开始运行时,执行一次
控制变量的修正语句:每轮循环结束会先进行控制变量修正运算,而后再做判断
case选择执行语法
case $variable in
    pattern1)
        分支1
        ;;
    pattern2)
        分支2
        ;;
    pattern3)
        分支3
        ;;
    *)
        分支N
esac
case支持glob网络的通配符:
* 
?
[]
a|b :a或者b

shell函数

把一段独立功能的代码当作一个整体,并定义一个函数名字,命名的代码段,就称之为一个函数。定义的函数代码段不会自动执行,需在调用的时候执行。调用函数就是批是代码中给出指定的函数名即可。函数可出现在任何位置,在代码执行时,都会被自动替换为函数代码。其函数命名不应该为命令名。其可在过程式编程中实现代码重用。以此实现模块化编程结构化编程.

函数的生命周期
函数的返回值
示例:给定一个用户名,取得用户的id号和默认shell
#!/bin/bash
#

userinfo() {
    if id "$username" &> /dev/null; then
        grep "^$username\>" /etc/passwd | cut -d: -f3,7
    else
        echo "No such user."
    fi
}

username=$1
userinfo

username=$2
userinfo 
传递参数给函数
示例:添加10个用户,其添加用户的功能使用函数实现,用户名做为参数传递给函数
                #!/bin/bash
                #
                # 5: user exists

                addusers() {
                    if id $1 &> /dev/null; then
                        return 5
                    else
                        useradd $1
                        retval=$?
                        return $retval
                    fi
                }

                for i in {1..10}; do
                    addusers ${1}${i}
                    retval=$?
                    if [ $retval -eq 0 ]; then
                        echo "Add user ${1}${i} finished."
                    elif [ $retval -eq 5 ]; then
                        echo "user ${1}${i} exists."
                    else
                        echo "Unkown Error."
                    fi
                done
函数变量的作用域
注意:在函数中定义变量尽量使用local来定义变量

=========

bash之数组

什么是数组?

存储多个元素的连续的内存空间,其数组只有一个名字,其数组的索引号从0开始。

定义一个数组
数组中元素的赋值方式
数组中的元素引用
数组的长度引用 (即数组中元素的个数 )
* ${#ARRAY_NAME[*]}
* ${#ARRAY_NAME[@]}

        注意:${#ARRAY_NAME},表示引用第一个元素的字符串长度
引用数组中的所有元素
数组元素切片
向非稀疏数组中追加元素
删除数组中的某元素
关联数组的定义

bash之信号捕捉

trap 命令
向脚本传递信号示例
    #!/bin/bash
    #
    trap 'echo "dou ni wan er."' INT
    trap 'echo "quit";exit1' INT
    
    注意:可以把捕捉信号定义在一个函数里,在其它位置调用,脚本参考<脚本合集>

bash之颜色设置

上一篇 下一篇

猜你喜欢

热点阅读