zoukankan      html  css  js  c++  java
  • shell语法

    shell 概述

    是什么

    shell 是一门计算机语言,和 python | Java一样,都可以编写程序
    shell字面意思:,:指操作系统,shell 是保护操作系统的 。
    计算机操作系统只能识别 0 和 1组成的机器码,现在我们是通过GUI|CLI 来间接操作操作系统
    GUI(图形化界面) | CLI(命令行) 在用户与操作系统之间,相当于桥梁、中介的作用,结构上看,GUI和CLI 保护操作系统
    GUI 与 CLI 就是通过 Shell 实现的

    分类 

    第一类:GUI样式的shell(图形化界面)
    第二类:CLI样式的shell(命令行)
    专指: Linux 下的 shell 编程

    怎么用

    流程
    1)、创建一个文本文档,后缀名是 .sh
    文档名要做到见名知意
    2)、再在文本文件中录入一个命令
    echo  "xxxx" 在命令行模式下直接输出数据
    规范:第一行固定格式 #!/bin/bash  指定shell解析器在linux位置
    作用:指定脚本解析的解释器
    3)、执行  .sh 文件(shell 脚本)
    方式1: sh(bash) shell文件
    方式2: 绝对路径(/xxx/yyy/abc.sh) 或 相对路径(./abc.sh),注意:要修改文件的权限 chmod 777 abc.sh
    方式3: source abc.sh(source 相当于 ./)
    01.sh
    #! /bin/bash
    #指定脚本解析的解释器
    #echo 是将结果输出到终端上
    echo "我是孙腾"
    执行shell脚本

    练习

    练习1:在命令行输出当前所在目录
    02.sh
    #! /bin/bash
    #指定脚本解析的解释器
    pwd
    执行shell脚本

    shell语法变量和运算符

    注释

    单行注释(常用):一次只注释一行
    格式: # 注释文本

    变量

    <u>变量创建:</u>
    
    	格式: 变量名=变量值
    
    	注意1:变量名
    
    	a)、不能数字开头
    
    	b)、变量名不能有空格这种特殊字符
    
    	c)、起名做到见名知意
    
    	d)、变量名不要使用关键字
    
    	注意2:赋值符号"="左右两侧不要有空格
    注意3:变量值
    
    	a)、变量值可以不使用引号,但是如果有空格,必须使用 "" or ''
    
    	b)、"" 和 '' 的区别,变量之间赋值时,如果是  "",那么赋的是变量的值,如果是 '' 只是赋值调用格式
    变量查询
    	格式:"${变量名}" -----  标准格式  打印时在写代码时候 一定要用双引号这个格式,不然会报莫名错误
    	注意:其他格式(不建议使用)
    	${变量名} or $变量名
    变量修改:
        格式:同增
        变量名=变量值
    变量删除:
        格式:unset 变量名

    变量分类

    本地(局部)变量
    只有当前 shell 可以使用的变量	 
    全局变量(静态变量)(了解)
    被多个 shell 共享的变量	(只能在一个终端窗口,不能跨终端,跨终端的env里面没有全局变量) 
    需求:如何将本地变量转换成全局变量
    思想:将本地变量设置为全局变量就是要将本地变量导出到共享空间
    格式: export 局部变量 
    查询全局变量: env
    注意1:如果是全局变量,建议变量名所有字母都大写
    注意2:全局变量要慎用
    变量(特殊变量)
    需求:编写shell动态获取某个目录下的子级(目录不一定)
    实现流程:
        1)、shell 调用时,可以传入要操作的目录
        格式: sh abc.sh 某个目录
        2)、shell 执行时,可以获取调用传入的目录
        格式:ls  $1 (代表传入的第一个参数)      
    上述流程其实就是传参以及参数解析的过程,这个参数就可以称之为内部变量
    语法总结:
    应用场景,程序执行时有些数据是可变的,可以调用脚本时,传入这些可变数据,脚本中解析获取
    调用格式: sh xxx.sh 参数1 参数2 参数3 .....
    解析格式: $N 获取第 N 个参数
    优点: 动态传值,更灵活
    $0 获取脚本文件名
    $* 获取所有参数
    $# 获取参数个数
    inner.sh
    #! /bin/bash
    #ls $1
    echo "第1个参数$1"
    echo "第2个参数$2"
    echo "第3个参数$3"
    echo "第9个参数$9"
    echo "第10个参数$10"
    echo "$0"
    echo "$*"
    echo "$#"
    执行

    练习:动态获取值

    扩展:读取键盘录入
    需求:编写shell动态获取某个目录下的子级(目录不一定,要让调用者指定)
    格式: read     -p     "提示语句:"     变量名 (注意:有空格!!!!)
    作用:执行到此时,程序挂起,等待用户录入数据,录入数据后,回车,录入的数据会赋值给变量
    优点:动态获取数据,更灵活!!!!!
    read.sh
    #! /bin/bash
    #1、用户录入目录
    read -p "请输入一个目录:" myDir
    #2、 获取目录子级
    ls "${myDir}"
    执行 

    变量特殊赋值(记住)

    需求:将某个命令的结果赋值给一个变量
    格式:变量名=`命令`

    练习

    使用shell脚本,输出当前所在的目录
    知识点:将命令结果赋值给变量
    shell脚本
    #! /bin/bash
    dir=`pwd`
    echo "当前所在目录是:${dir}"
    执行shell脚本
    计算指定目录下有多少个文件,用shell脚本实现
    新知识点:获取某个目录下子级个数
            固定格式:ls 目录 | wc -l
    参数shell脚本
    #! /bin/bash
    #动态获取某个目录,然后在获取目录下子级的个数
    #方案一:读取脚本调用时传入的参数
    #调用 sh test03.sh /root
    #执行 ls $1 | wc -l
    count=`ls $1 | wc -l`
    echo "$1目录下的子级:${count}"
    执行
    键盘录入shell脚本
    #! /bin/bash
    #动态获取某个目录,然后在获取目录下子级的个数
    #方案一:读取键盘录入的数据
    read -p "请你输入一个路径" myDir
    # 获取目录子级个数
    count=`ls ${myDir} |wc -l`
    echo "${myDir}下的子级个数为:${count}"
    执行

    运算符

    算数运算符
        格式: $((数学表达式))
        运算符:	+ - * / % == 加减乘除取余
        注意: 一般计算机语言中除法运算只取商   
    比较运算符
        返回的是 boolean 值(特殊: 0为true 1为false)
        格式: [ 表达式 ] ---- 注意:[] 中有两个空格,两个空格中添加表达式
        查看结果: $? 
        运算符: 不能直接使用 > < >= <= == != 
        使用对应的参数  -gt(>) -lt(<) -ge(>=) -le(<=) -eq(==) -ne(!=) **记住**
    逻辑运算符
        返回 boolean 值(<u>特殊: 0为true 1为false</u>)
        格式: [ 表达式 ]
        运算符: -a 与  -o或 	!非     
    字符串比较:返回 boolean 值
        格式: [ 表达式 ]
    
    运算符: == 判断两个字符串内容是不是一样
    	      != 判断两个字符串内容是不是不一样
    	      -z 判断单个字符串长度是不是0(判断字符串是不是空)
    文件判断:返回 boolean 值
            格式: [ 表达式 ]
            运算符:  -d: 判断是不是文件夹
            -f: 判断是不是文件
            -e: 判断是不是存在
    #常用的文件测试操作符
    #常用操作符                        #说明
    -f 文件,全称file            #文件存在且为普通文件则为真,表达式成立
    -d 文件,全称directory       #文件存在且为目录则为真,表达式成立
    -s 文件,全称size            #文件存在且大小不为0为真
    -e 文件,全称exist           #文件存在则为真
    -r 文件,全称read            #文件存在且为可读则为真,表达式成立
    -w 文件,全称write           #文件存在且可写为真,表达式成立
    -x 文件,全称executable      #文件存在且可执行为真
    -L 文件,全称link            #文件存在且为链接文件为真
    f1 -nt f2,英文newer than    #文件f1比文件f2新则为真,根据文件修改时间计算
    f1 -ot f2,英文older than    #文件f1比文件f2旧为真,根据修改时间计算

    练习

    判断 /home/admin(/root)目录是否为空
    思路:现获取目录子级文件个数,判断是否大于 0
    #! /bin/bash
    #统计指定目录文件个数
    read -p "请输入要统计的目录:" str
    count=`ls ${str} | wc -l`
    echo "${str}目录下共有${count}"

    shell语法函数

    shell函数常用方式

    1. 简单函数(无参)
    2. 带参函数(调用函数时带参数)
    3. 带参函数(执行脚本时调用参数)

    简单函数

    说明:自定义函数,调用函数名

    格式

    定义函数:
        函数名(){
            语句
            ...
        }
    调用函数:
        函数名
    案例1
    需求:定义fun01函数,打印 this is a funcation
    #! /bin/bash
    #声明一个函数
    hello(){
    	echo "hello function!"
    }
    #调用函数
    hello
    执行

    带参函数(调用函数时带参数)

    说明:调用函数名时带参数

    格式

    定义函数:
        函数名(){
            语句$n
            ...
        }
    调用函数:
        函数名 参数
    需求:定义fun01函数,调用的时候传递参数,在函数内部获取参数
    #! /bin/bash
    # 有参数的函数
    getSum(){
    	echo "两个数字的和为:$(($1+$2))"
    	echo "第一个参数 $1"
    	echo "第二个参数 $2"
    	echo "第三个参数 $3"
    	echo "第十参数 $10"
    	echo "文件名:$0"
    	echo "所有参数:$*"
    	echo "参数个数:$#"
    }
    # 调用函数
    getSum 4 2 3 4 5 6 7 8 9 a b
    结果

    带参函数(执行脚本时调用参数)

    说明:执行脚本时附带参数

    格式

    定义函数:
        函数名(){
            语句$n
            ...
        }
    调用函数:
        函数名 $n
    案例
    需求:定义fun01函数,执行脚本时传递参数 lisi,打印:nihao lisi
    #!/bin/bash
    # 定义函数名
    fun01(){
         echo "ni hao $1"
    }
    
    # 调用函数
    fun01 $1
    # 执行脚本调用
    # bash /root/fun03.sh lisi

    带返回值的函数

    #! /bin/bash
    #带返回值的函数
    #1、声明函数
    getSum(){
    	result="$(($1+$2))"
    	#return "${result}"
    	echo "函数中的result:${result}"
    	return 0
    }
    #2 调用函数
    getSum 3 4
    #打印返回值
    echo "函数返回的结果是:$?"
    echo "函数外调用result:${result}"

    函数加强练习

    使用函数实现,输入任意两个数,打印求和结果
    #! /bin/bash
    #带返回值的函数
    #1、声明函数
    getSum(){
    	result="$(($1+$2))"
    	#return "${result}"
    	echo "函数中的result:${result}"
    	return 0
    }
    #2 调用函数
    getSum 3 4
    #打印返回值
    echo "函数返回的结果是:$?"
    echo "函数外调用result:${result}"
    ###### 读取键盘录入,录入长方形的长和宽,编写求周长和面积的函数,调用并输出周长和面积的值
    #! /bin/bash
    #1读取键盘录入的长和宽
    read -p "请输入长:" length
    read -p "请输入宽:"  width
    #2求周长函数
    getAllLength(){
    	echo "周长是:$((($1+$2)*2))"
    }
    #3求面积函数
    getArea(){
    	echo "面积是:$(($1*$2))"
    }
    
    #调用周长函数
    getAllLength "${length}" "${width}"
    #调用面积函数
    getArea "${length}" "${width}"
    说明:使用函数;提示输入一个目录,在此目录中进行提示要创建的文件名;如果该目录不存在,提示目录不存在;
              如果输入的文件已存在,提示该文件已存在,否则创建该文件;
    #! /bin/bash
    #处理文件的函数
    doMyFile(){
    	#开始处理
    	#文件存在,给出提示,不存在就创建
    	if [ -f $1 ]
    	then
    		echo "文件已经存在了"
    	else
    		echo "文件开始创建"
    		echo "......"
    		touch $1
    		echo "文件创建完毕"
    	fi
    }
    #处理目录的函数
    doMyDir(){
    	#获取传入的目录$1
    	#如果不是目录给出提示,是目录操作文件
    	if [ -d $1 ]
    	then
    		echo "操作文件"
    		# 让用户录入文件名
    		read -p "请你录入一个文件:" myFile
    		# 进入目录
    		cd $1
    		#操作文件
    		doMyFile ${myFile}		
    	else
    		echo "你输入的不是目录"
    	fi
    }
    read -p "请你输入一个目录:" myDir
    #操作目录,单独一个函数实现
    doMyDir ${myDir}

    shell流程控制

    说明:如果条件成立,则执行then后面语句,否则执行else后面语句
    格式:
        if [ 条件 ]
        then
            语句块
        else
            语句块
        fi
    提示:
        1. []中括号在shell中表示为表达式,表达式前后必须有空格;如[ 1 -gt 0 ]
        2. 条件中有变量或字符串使用""括起来
        3. then可以和if语句写在一行,then语句之前需要添加; 如:if [ 条件 ];then
        4. 结尾有关键字fi

    if流程控制语句

    需求: 录入年龄,判断是否成人,如果成人了输出"成年人"
    #! /bin/bash
    #if单分支实现
    #1 让用户录入年龄
    read -p "让用户录入你的年龄" age
    #2 年龄判断
    if [ ${age} -ge 18 ]
    then
    	echo "成年人"
    fi

    if..else流程控制语句

    (需求: 录入年龄,判断是否成人,如果成人了输出"成年人",否则输出未成年)
    #! /bin/bash
    #if多分支实现
    #1 让用户录入年龄
    read -p "让用户录入你的年龄" age
    #2 年龄判断
    if [ ${age} -ge 18 ]
    then
    	echo "成年人"
    else
    	echo "未成年人"
    fi

    if...elif多分支控制语句

    #! /bin/bash
    #if多分支实现
    #1 让用户录入年龄
    read -p "让用户录入你的年龄" age
    #2 年龄判断
    if [ ${age} -lt 18 ]
    then
    	echo "未成年人"
    elif [ ${age} -ge 18 -a ${age} -le 30 ]
    then
    	echo "成年人"
    elif [ ${age} -gt 30 -a ${age} -lt 50 ]
    then
    	echo "中年人"
    else
    	echo "老年人"
    fi
    

    练习

    练习1:判断用户输入的用户名和密码是否为admin 123456,如果是则提示登录成功,否则提示失败
    #! /bin/bash
    read -p "输入用户名" username
    read -p "输入密码" passwd
    if [ ${username} == "admin" -a ${passwd} == "123456" ]
    then
    	echo "登陆成功"
    else
    	echo "登陆失败"
    fi
    练习2:输入数字,判断是否大于0,如果大于0则将该数字-1并输出,否则+1输出
    #! /bin/bash
    read -p "请你录入一个数字" num
    # 如果数字小于0减1 否则加1
    if [ ${num} -gt 0 ]
    then
    	num=$((${num} + 1))
    	echo "${num}"
    else
    	num=$((${num} - 1))
    	echo "${num}"
    fi
    练习3:判断用户输入的目录是否存在,如果存在则统计目录下的文件个数,否则提示用户该目录不存在
    #! /bin/bash
    read -p "请输入一个目录:" myDir
    if [ -d ${myDir} ]
    then
    	# 统计文件个数
    	count=`ls ${myDir} | wc -l`
    	echo "${myDir}目录下文件个数是:${count}"
    else
    	echo "你输入的目录不存在"
    fi
    练习3:判断用户输入的内容是否为空,为空则提示,不为空则判断是否为目录,不为目录则判断是否为文件,否则提示错误信息
    #! /bin/bash
    read -p "请你输入一个文件或目录" myfile
    if [ -z ${myfile} ]
    then
    	echo "录入的路径不能为空"
    elif [ -f ${myfile} ]
    then
    	echo "录入的路径是文件"
    elif [ -d ${myfile} ]
    then
    	echo "录入的路径是文件夹"
    else
    	echo "录入的路径有误"
    fi

    流程控制分支实现之case

    条件符合执行相应的代码块,类似于if..elif..语句
    
    格式:
        case 变量 in
            值1 )
                echo "语句块1"
                ;;
            值2 )
                echo "语句块2"
                ;;
            值3 | 值4 )
                echo "语句块3"
                ;;
            ...
            * )
                echo "语句块4-默认值"
                ;;
            esac
    提示:
        1. 星号(*)相当于else,条件都不符合时执行;
        2. 双分号(;;)是必须的,执行完相应语句块跳出程序;
        3. 竖线(|)用于分割多个值,相当于 值1 or 值2 ;
        4. 值可以为字符串、数字、区间值( [0-9] | [a-z] | [A-Z] )、组合词[aA][bB][cC]
        4. 结尾必须有esac
    需求:模拟游戏级别选择,读取键盘录入的数字,如果是数字1,那么输出简单,    如果是数字2,那么输出一般,如果是数字3输出困难,其他输出数据有误
    #! /bin/bash
    read -p "请输入一个数据:" num
    case "${num}" in
    1)
    	echo "游戏难度简单"
    	;;
    2)
    	echo "游戏难度一般"
    	;;
    3)
    	echo "游戏难度困难"
    	;;
    *)
    	echo "你输入的数据有误"
    	;;
    esac

    shell 语法:流程控制循环实现之for

    遍历读取列表元素,列表元素遍历完毕,结束语句;
    
    语法格式:
    for 值 in 列表
    do
        执行语句
    done

    练习

    需求:遍历 1-10之间所有整数
    #! /bin/bash
    # 循环遍历
    #for ele in 1 2 3 4 5 6 7 8 9 10
    #for ele in `seq 10`
    #for ele in `seq 5 10`
    for ele in `seq 5 2 10`
    do
    	echo "元素:${ele}"
    done
    注意
    seq 命令优化 for 循环
    格式1: seq 参数NUM ---> 默认遍历 [1-NUM] 之间的所有整数
    格式2:    seq 参数NUM1 参数NUM2 ----> 遍历 [NUM1-NUM2]之间的所有整数
    格式3:    seq 参数NUM1 参数NUM2 参数NUM3 ----> 遍历 [NUM1-NUM3] 之间的整数,但是每次递增 NUM2 值
    	       不指定 NUM2 每次默认递增1, NUM2 又称之为步进值
    求1-100之间的和
    #! /bin/bash
    #计算1-100之间的整数和
    sum=0
    for ele in `seq 100`
    do
    	sum=$((${sum}+${ele}))
    done
    # 输出变量的值
    echo "1-100之间的和是:${sum}"

    shell 语法:流程控制循环实现之while

    	while [ boolean表达式 ]
    
    	do
    
    		code.....
    
    	done

    (需求:遍历 1-10之间所有整数)
    #! /bin/bash
    #while循化遍历1-10
    num=1
    while [ ${num} -le 10 ]
    do 
    	echo "${num}"
    	num=$((${num}+1))
    done
    求1-100之间的和
    #! /bin/bash
    #!while循环求1-100的整数和
    sum=0
    num=1
    while [ ${num} -le 100 ]
    do
    	sum=$((${sum}+${num}))
    	num=$((${num}+1))
    done
    #循环结束
    echo "1-100整数和是:${sum}"

    shell 语法其他:重定向

    是什么?
    可以将命令产生的数据保存到磁盘文件
    为什么?
    一种序列化(持久化)机制,可以持久的保存数据
    怎么用?
    格式1: 命令 1>> 磁盘文件 (将正常命令的结果输出到文件) 
    格式2: 命令 2>> 磁盘文件 (将错误命令的结果输出到磁盘文件)

    shell 语法其他:数组

    是什么?
    数组也是变量,但是是特殊的变量,一般变量只能存储一个值,而数组可以存储多个值
    怎么用?
    数组创建
    	变量名=(值1 值2 值3 .... )
    数组查询
        查某个元素: ${数组名[索引 ]} //索引从 0 开始
        查询所有元素: ${数组名[*]} | ${数组名[@]}
        查询元素个数: ${#数组名[*]} | ${#数组名[@]}
    数组修改
        变量名[索引]=新值
        数组删除
        unset 数组名(同变量删除)

  • 相关阅读:
    【代码审计】XDCMS 报错注入
    【渗透测试】MS17-010 "永恒之蓝" 修复方案
    【代码审计】MenInfo文件包含漏洞
    【代码总结】数据库抽象层PDO
    【代码总结】PHP面向对象之接口与多态性应用
    【代码总结】PHP面向对象之抽象类
    东哥手把手带你刷二叉树(第一期)
    二叉树的序列化,就那几个框架,枯燥至极
    二叉堆详解实现优先级队列
    递归反转链表的一部分
  • 原文地址:https://www.cnblogs.com/st998/p/13825218.html
Copyright © 2011-2022 走看看