• Shell基础


    1. 什么是shell
    1.1 命令分类
    1.内置命令:程序代码内置到bash命令中,
    查看命令帮助
    help cd
    man cd 就会看到所有内置命令的帮助文档。
    2.普通命令:程序文件存放在磁盘上 /bin/ls
    查看命令帮助
    ls --help
    man ls
    1.2 判断内置命令方法:
    [root@web01 ~]# type ls
    ls is aliased to `ls --color=auto'
    [root@web01 ~]# type cd
    cd is a shell builtin

    2. shell脚本
    一个程序文件,放了大量的linux命令
    好的shell脚本,不只是有命令,还有变量,逻辑判断if for case while
    Shell的优势在于处理操作系统底层的业务,因为有大量的Linux系统命令
    php python go

    3. 如何写一个优美的Shell脚本
    3.1 统一的脚本存放目录
    mkdir -p /server/scripts
    3.2 推荐使用vim命令写脚本,支持语法高亮
    vim first.sh 规范写法以.sh结尾
    3.3 脚本文件的第一行必须写上#!/bin/bash
    #! 叫做“幻数” 告诉内核使用/bin/bash来解释我的脚本
    # 除了第一行之外都表示后面跟的是注释
    echo "hello" # 这里还是注释 echo 'world' 这个命令不生效
    3.4 第2行~第n行 加上版权信息
    3.5 变量区段
    name=hefan 等号左右都不能有空格
    3.6 命令语句区段
    echo $name 使用变量使用$符号
    3.7 执行Shell脚本
    第一种方式:(推荐)
    sh new.sh或bash new.sh sh是bash的软链接,sh和bash两种方式没有任何区别
    第2种:(不推荐使用)
    /server/scripts/new.sh 这种全路径执行需要文件有可执行权限,第一种方法则不需要
    第3种:
    source new.sh 或 . new.sh source和.的功能一模一样
    sh 是创建一个新的进程读取脚本执行脚本,和当前的shell窗口进程不资源共享,
    例如name变量不会被当前shell窗口继承或知道。
    source或. 在当前shell窗口从脚本文件中读取命令执行
    应用场景:定时任务的脚本中source /etc/profile

    4. 变量区段
    4.1 变量的分类
    4.1.1.全局变量:在所有进程及其子进程生效,例如对脚本中生效,能在脚本中使用这个变量
    export OLDBOY=1 设置环境变量,但是还只是当前Shell窗口生效
    env 查看环境变量
    永久生效 需要写入环境变量配置文件/etc/profile(常用)
    常用变量配置文件
    全局:
    /etc/profile
    /etc/profile.d
    /etc/bashrc (推荐)
    只对当前用户:
    ~/.bash_profile
    ~/.bashrc (推荐)
    4.1.2.局部变量:只对当前进程生效,在脚本中不生效
    变量名的规范:由字母、数字、下划线组成,必须以字母开头
    oldboy
    oldboy123
    123old 不是变量
    _abc 系统用的,我们不用
    写法规范:驼峰语法:第一个单词的首字母小写,从第2个单词开始首字母大写
    passWord
    oldBoyEdu
    oneTwoThreeFour
    4.1.3.怎么区分全局变量和局部变量:就看有没有用export命令定义
    有export就是全局变量,没有export局部变量
    [root@web01 scripts]# tail -2 /etc/profile
    export OLDBOY=1
    oldgirl=1
    [root@web01 scripts]# env|grep OLDBOY
    OLDBOY=1
    [root@web01 scripts]# env|grep oldgirl
    4.1.4.特殊变量
    位置变量:跟命令行文件名或者参数的所处位置有关
    $0 代表执行的脚本名称
    echo $0
    [root@web01 scripts]# sh arg.sh
    arg.sh
    [root@web01 scripts]# sh /server/scripts/arg.sh
    /server/scripts/arg.sh
    $1 $2 $3 ... $n n为任意正整数,$# 表示你传入参数的个数
    [root@web01 scripts]# cat arg.sh
    #!/bin/bash
    echo $0
    echo "第一个变量:$1"
    echo "第2个变量:$2"
    echo "第3个变量:$3"
    echo "参数总个数为:$#"
    补充:变量之"金庸新著"
    $10 和 ${10}
    $weekday 和 ${week}day
    为了避免歧义,变量左右都加上大括号。
    $* 一般表示命令行所有参数,不加引号同$@;如果给$*加上双引号
    例如: "$*",则表示将所有的参数视为单个字符串,相当于"$1$2$3"
    $@ 一般表示命令行所有参数,不加引号同$*;如果给$@加上双引号
    例如: "$@",则表示将所有参数视为不同的独立字符串,相当于"$1" "$2" "$3" "……",这是将参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。
    推荐使用"$@"
    [root@web01 ~]# set -- "I am" handsome boy..
    [root@web01 ~]# echo $1
    I am
    [root@web01 ~]# echo $2
    handsome
    [root@web01 ~]# echo $3
    boy..
    [root@web01 ~]# echo $*
    I am handsome boy..
    [root@web01 ~]# echo $@
    I am handsome boy..
    [root@web01 ~]# for i in $*;do echo $i;done
    I
    am
    handsome
    boy..
    [root@web01 ~]# for i in $@;do echo $i;done
    I
    am
    handsome
    boy..
    [root@web01 ~]# for i in "$*";do echo $i;done
    I am handsome boy..
    [root@web01 ~]# for i in "$@";do echo $i;done
    I am
    handsome
    boy..
    状态变量:
    $?:判断上一条命令是否执行成功,$?为0表示上一条命令执行成功,$?非零表示上一条命令执行不成功
    脚本结尾隐藏执行了exit(等效于exit 0)
    因此可以自定义返回值 exit 1
    4.2 变量的定义
    直接赋值
    name=zhangyao
    dir=/server/scripts
    命令行传参 传递参数 利用位置参数$0 $1 ...
    交互式设置参数 read -s 用于密码输入,不明文显示密码 -t 设置超时时间 -p 接提示语句
    [root@web01 scripts]# read
    oldboy
    [root@web01 scripts]# echo $REPLY
    oldboy
    [root@web01 scripts]# read name
    oldboy
    [root@web01 scripts]# echo $name
    oldboy
    [root@web01 scripts]# read passWord
    123456
    [root@web01 scripts]# echo $passWord
    123456
    [root@web01 scripts]# unset name # 删除变量
    [root@web01 scripts]# echo $name

    [root@web01 scripts]# read -p "请输入你的姓名:" name
    请输入你的姓名:oldboy
    [root@web01 scripts]# read -s -p "请输入你的密码:" passWord
    请输入你的密码:[root@web01 scripts]#
    [root@web01 scripts]# echo $passWord
    12345678
    [root@web01 scripts]# read -t 5 -p "请输入你的姓名:" name
    请输入你的姓名:
    [root@web01 scripts]# vim readname.sh
    #!/bin/bash
    read -p "请输入你的姓名:" name
    read -s -p "请输入你的密码:" passWord
    echo
    echo "$name $passWord"
    4.3 变量的字串
    [root@web01 scripts]# name=oldboy
    [root@web01 scripts]# echo ${name} # 打印变量
    oldboy
    [root@web01 scripts]# echo ${name}|wc -L
    6
    [root@web01 scripts]# echo ${#name} # 获取变量值的长度
    6
    [root@web01 scripts]# echo $#name # 注意避免歧义
    0name
    截取字符串
    [root@web01 scripts]# echo ${name:1:1} # 变量:截取字符起始编号:截取长度
    l
    [root@web01 scripts]# echo ${name:1:3}
    ldb
    [root@web01 scripts]# echo ${name:4:1}
    o
    删除字符串
    [root@web01 scripts]# OLDBOY=abcABC123ABCabc
    [root@web01 scripts]# echo $OLDBOY
    abcABC123ABCabc
    [root@web01 scripts]# echo ${OLDBOY#a*C} # 从左开始匹配,一个#表示最短删除
    123ABCabc
    [root@web01 scripts]# echo ${OLDBOY##a*C} # 从左开始匹配,2个##表示最长删除
    abc
    [root@web01 scripts]# echo ${OLDBOY%a*c} # 从右开始匹配,一个%表示最短删除
    abcABC123ABC
    [root@web01 scripts]# echo ${OLDBOY%%a*c} # 从右开始匹配,2个%%表示最长删除
    替换
    [root@web01 scripts]# echo ${OLDBOY/abc/ABC}
    ABCABC123ABCabc
    [root@web01 scripts]# echo ${OLDBOY//abc/ABC}
    ABCABC123ABCABC
    变量字串的案例--批量改名
    [root@web01 test]# touch stu_102999_{1..5}_finished.jpg
    [root@web01 test]# ls
    stu_102999_1_finished.jpg stu_102999_3_finished.jpg stu_102999_5_finished.jpg
    stu_102999_2_finished.jpg stu_102999_4_finished.jpg
    [root@web01 test]# mv stu_102999_1_finished.jpg stu_102999_1^Cpg
    [root@web01 test]# f=stu_102999_1_finished.jpg
    [root@web01 test]# echo ${f/_finished/}
    stu_102999_1.jpg
    方法1:
    for f in `ls *.jpg`;do mv $f `echo ${f%_finished*}.jpg`;done
    方法2:
    for f in `ls *.jpg`;do mv $f `echo ${f/_finished/}`;done

    特殊用法
    [root@web01 test]# echo ${var-/server/}
    /server/
    [root@web01 test]# echo $var
    [root@web01 test]# echo ${var=/server/}
    /server/
    [root@web01 test]# echo $var
    /server/

    字串和管道的性能对比
    [root@web01 ~]# chars=fkfmkfdmgkl
    [root@web01 ~]# time for i in $(seq 11111);do count=${#chars};done
    real 0m0.126s
    user 0m0.123s
    sys 0m0.002s
    [root@web01 ~]# time for i in $(seq 11111);do count=`echo ${chars}|wc -L`;done
    real 0m23.109s
    user 0m2.885s
    sys 0m3.368s

    4.4 变量的数值计算
    4.4.1. (())
    [root@web01 ~]# ((a=1+1))
    [root@web01 ~]# echo $a
    2
    [root@web01 ~]# b=$((2+2))
    [root@web01 ~]# echo $b
    4
    [root@web01 ~]# echo $((3+4))
    7

    [root@web01 ~]# i=1
    [root@web01 ~]# echo $((i++))
    1
    [root@web01 ~]# echo $i
    2
    [root@web01 ~]# echo $((i++))
    2
    [root@web01 ~]# echo $i
    3
    [root@web01 ~]# i=1
    [root@web01 ~]# echo $((++i))
    2
    [root@web01 ~]# echo $i
    2
    [root@web01 ~]# echo $((++i))
    3
    [root@web01 ~]# echo $i
    3
    4.4.2.expr
    [root@web01 ~]# expr 2+2
    2+2
    [root@web01 ~]# expr 2 + 2 # 必须有空格
    4
    [root@web01 ~]# expr a + 1 # 常用的用途:判断其中参数是否为整数
    expr: non-numeric argument
    [root@web01 ~]# echo $?
    2
    [root@web01 ~]# expr 2 + 2
    4
    [root@web01 ~]# echo $? # 通过返回值判断
    0
    [root@web01 ~]# expr 2.1 + 2 # 不支持小数
    expr: non-numeric argument
    [root@web01 ~]# expr -2 + 2 # 支持负整数
    0
    使用场景:
    [root@web01 scripts]# vim judge.sh
    #!/bin/bash
    num1=$1
    num2=$2
    [ $# -ne 2 ] && echo "Usage:sh $0 num1 num2" && exit 1
    expr $num1 + 1 &>/dev/null
    [ $? -ne 0 ] && echo "第一个参数不是整数。" && exit 2
    expr $num2 + 1 &>/dev/null
    [ $? -ne 0 ] && echo "第二个参数不是整数。" && exit 3
    echo $(($num1+$num2))
    4.4.3. bc 支持小数运算
    [root@web01 scripts]# echo 1+2|bc
    3
    [root@web01 scripts]# echo 1+2.1|bc
    3.1
    [root@web01 scripts]# bc # 交互方式
    bc 1.06.95
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type `warranty'.
    1+2
    3
    [root@web01 scripts]# echo "scale=2;355/113"|bc # scale指定保留小数位数
    3.14
    [root@web01 scripts]# echo "scale=6;355/113"|bc
    3.141592

    [root@web01 scripts]# echo `seq -s '+' 10`=`seq -s '+' 10|bc`
    1+2+3+4+5+6+7+8+9+10=55
    4.4.4. awk计算数字
    [root@zyops ~]# echo "7.7 3.8"|awk '{print ($1-$2)}'
    3.9
    [root@zyops ~]# echo "358 113"|awk '{print ($1-3)/$2}'
    3.14159
    [root@zyops ~]# echo "3 9"|awk '{print ($1+3)*$2}'
    54
    [root@backup scripts]# awk BEGIN'{print 1.2+3.3}'
    4.5

    5.命令语句区段
    5.1 条件判断
    5.1.1.语法:[ -f /etc/hosts ] 先敲一对[],然后回退一格,敲2个空格,再回退一格
    5.1.2.文件判断
    -f 判断文件存在并且为普通文件,则表达式为真
    [root@web01 scripts]# [ -f /etc/hosts ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    [root@web01 scripts]# [ -f /etc/host ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    -d 判断文件存在并且为目录,则表达式为真
    [root@web01 scripts]# [ -d /etc/ ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    [root@web01 scripts]# [ -d /etc1/ ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    5.1.3. 字符串判断
    -z 判断字符串为0,则表达式为真 zero 语法要求:字符串左右必须有双引号
    [root@web01 scripts]# var=123
    [root@web01 scripts]# [ -z "$var" ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    [root@web01 scripts]# [ -z "$var1" ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    -n 判断字符串非0,则表达式为真
    [root@web01 scripts]# [ -n "$var" ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    [root@web01 scripts]# [ -n "$var1" ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    "串1" = "串2" 相等成立,表达式为真
    语法要求:等号两侧也要求有空格。
    [root@web01 scripts]# [ "$var" = "123" ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    "串1" != "串2" 不相等成立,表达式为真
    [root@web01 scripts]# [ "$var" != "123" ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    5.1.4. 整数判断
    -eq 等于 equal [ $? -eq 0 ]
    -ne 不等于 not equal [ $? -ne 0 ]
    -gt 大于 greater than
    -ge 大于等于 greater equal
    -lt 小于 less than
    -le 小于等于 less equal
    [root@web01 scripts]# [ "1" = "1" ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    表达式成立
    # 大于,小于都需要转译
    [root@web01 scripts]# [ "1" > "1" ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    [root@web01 scripts]# [ "1" < "1" ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    5.1.5. 逻辑操作符
    与(-a) 或(-o) 非(!)
    [root@web01 scripts]# [ "$var" = "123" -a 1 -eq 1 ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    [root@web01 scripts]# [ "$var" = "123" -a 1 -eq 0 ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    [root@web01 scripts]# [ "$var" = "123" -o 1 -eq 0 ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立
    [root@web01 scripts]# [ "$var" = "456" -o 1 -eq 0 ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    [root@web01 scripts]# [ "$var" = "123" -a 1 -eq 0 ] && echo "表达式成立" || echo "表达式不成立"
    表达式不成立
    [root@web01 scripts]# [ "$var" = "123" -a ! 1 -eq 0 ] && echo "表达式成立" || echo "表达式不成立"
    表达式成立

    案例:开发3个shell脚本比较2个整数大小
    1. 分别以定义变量,脚本传参以及read读入的方式写3个脚本。
    2. 用条件表达式(禁止if语句)进行判断。
    3. 将2个整数的比较结果输出到屏幕,出错需要提示。

    6. 获取随机数的方法
    6.1 系统变量$RANDOM
    [root@web01 scripts]# echo $RANDOM
    18832
    [root@web01 scripts]# echo $RANDOM|md5sum
    0828025a694bb190d15dc7880607e810 -
    6.2 UUID
    [root@web01 scripts]# uuidgen
    049ce4d3-ba3e-495f-aae5-73904033d59c

    7、shell脚本调试
    windows 的换行符是 linux是 ,转换命令:dos2unix hello.sh
    sh -x 脚本
    set -x 指定调试范围
    set +x
    [root@web01 scripts]# vim arg.sh
    #!/bin/bash
    echo $0
    echo "第一个变量:$1"
    set -x
    echo "第2个变量:$2"
    set +x
    echo "第3个变量:$3"
    echo "第4个变量:$4"
    echo "第5个变量:$5"
    echo "第10个变量:${10}"
    echo "参数总个数为:$#"
    echo $1 $2 $3
    echo $*
    echo $@
    "arg.sh" 29L, 577C written
    [root@web01 scripts]# sh arg.sh
    arg.sh
    第一个变量:
    + echo $'3472542542344270252345217230351207217357274232'
    第2个变量:
    + set +x
    第3个变量:
    第4个变量:
    第5个变量:
    第10个变量:
    参数总个数为:0

    参考连接:
            http://oldboy.blog.51cto.com/2561410/1867160

  • 相关阅读:
    Day09 约束
    Day08 数据处理
    Day07 创建和管理表
    Day06 子查询
    Appium学习_01(连接、apppackage名查询、appactivity名查询)
    我的读书方法
    Python自动化学习记录
    FineReport帆软报表学习积累
    ERP企业资源管理 详解
    Centos7学习记录
  • 原文地址:https://www.cnblogs.com/xwupiaomiao/p/9823612.html
Copyright © 2020-2023  润新知