Shell Script

概述

Shell是命令行解释器,它接受应用程序用户命令然后调用操作系统内核

Shell可以嵌套

在这里插入图片描述

Shell 脚本shell script)是种为 shell 编写脚本程序。常说的shell通常都是指 shell 脚本,但shell和shell script两个不同的概念。通常说“shell编程”都是指 shell 脚本编程,不是指开发 shell 自身。

脚本#!/bin/sh#!/bin/bash#!/bin/dash开头,用于指定解析器

来写个Hello Shell

Linux下面用命令如何运行.sh文件方法

  1. 直接./加上文件名.sh,如运行hello.sh为./hello.sh【hello.sh必须有x权限,即执行权限
  2. 直接shbash加上文件名,如运行hello.sh为sh hello.sh【hello.sh无需x权限,即执行权限
  3. source或者.(简写),都能实现sh一样的效果。但不同点在于,前面方式创建子shell(启动了个sh进程),在子shell里执行命令,而source方式直接在当前shell执行。

变量

系统预设变量

前面提到子shell的存在,使不使用的区别就在于环境变量继承关系。在子shell设置当前变量,父shell是不可见的。

常用系统变量:HOME、PWD、SHELL、USER

全局变量局部变量

用户自定义变量

基本语法

深入学习变量

变量默认字符串

使用$((<expression>))$[<expression>]括号里放表达式

使用readonly关键字可以让变量只读

撤销指定变量

特殊变量

PATH对应当前配置环境变量

$<number>number数字$0表示当前脚本名称(绝对路径),$1 ~ $9代表一到九个参数,十以上的参数需要用大括号包含${<number>}例如$<11>

$#获取所有输入参数个数,常用于循环判断参数个数是否正确,以及加强脚本的健壮性。

$*$@。两者都是代表命令行中所有的参数,不过$*字符串$@是实际的数组。若不加双引号,两者是一样的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat paramater.sh
    #!/bin/sh
    echo script name: $0
    echo 1st paramater: $1
    echo 2st paramater: $2
    echo parameter numbers: $#
    echo $*
    echo $@
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ sh paramater.sh a b
    script name: paramater.sh
    1st paramater: a
    2st paramater: b
    parameter numbers: 2
    a b
    a b
    

$?最后一次执行的命令返回状态。若值为0,表正确执行了;若不为0(具体是啥,由命令自己决定),则证明上个命令执行不正确;

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ ls
    helloShell.sh  paramater.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ fajefpewi
    -bash: fajefpewi: command not found
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    127
    

运算符

使用expr关键字可以实现计算功能,要注意参数之间用空格隔开,否则会被视为字符串。另外,像*号由于默认视为通配符,所以要使用表示视其为普通的*号。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ expr 5 + 5
    10
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ expr 5 * 5
    25
    

前面提到过使用[]或者(())方式实现运算,只要把表达式放到里面就好了。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $[6 / 2]
    3
    

赋值。下面分别展示两者运算后的赋值方法$(<command>)实现命令替换功能,执行内部的command,然后输出到指定位置

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_a=$((6*6))
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_a
    36
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_b=$(expr 4 - 5)
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_b
    -1
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_c=`expr 5 + 6`
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_c
    11
    

写个加法脚本

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat add.sh
    #!/bin/sh
    sum=$(($1+$2))
    echo sum=$sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./add.sh 34 43
    sum=77
    

条件判断

判断状态

使用test关键字,语法test <condition>,下面是示例,使用$?获取语句执行状态0true)。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_a
    hello
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ test $var_a = HELLO
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ test $var_a = hello
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    

使用[ <condition> ],虽然也是中括号,但不同于前面的是,要求前后都留有空格

  • 条件非空即为true例如

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ hello ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ [  ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    

常用判断条件

两个整数之间比较

比较

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ 4 -ge 4 ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    

注意如果使用(())语法,那么括号内是可以直接使用<>=符号的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ if ((1 > 2)); then echo YES; else echo NO; fi
    NO
    

判断文件是否有对应权限

断言

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ ll
    total 12
    -rwxr-xr-x 1 xuegao xuegao  39 Mar  7 00:07 add.sh
    -rwxr-xr-x 1 xuegao xuegao  51 Mar  6 01:13 helloShell.sh
    -rw-r--r-- 1 xuegao xuegao 120 Mar  7 00:03 paramater.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ -x paramater.sh ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    

按照文件类型进行判断

断言

连接

&amp;&amp;表示上条命令执行成功时,执行下条命令;||表示上条命令执行失败后,执行下条命令;

示例:

xuegao@xuegao-PC:~/dev/workspace/script/shell$ ls
add.sh  helloShell.sh  paramater.sh
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f add.sh &amp;&amp; echo OK
OK
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f addddd.sh &amp;&amp; echo OK
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f addddd.sh &amp;&amp; echo OK || echo failer
failer

流程控制

if 判断

分支,有两种写法

表达式可以使用连接符,下面是例子

  • xuegao@LAPTOP-XUEGAO:~/temp/script$ echo $a
    23
    xuegao@LAPTOP-XUEGAO:~/temp/script$ if [ $a -gt 18 ] && [ $a -lt 36 ]; then echo OK; fi
    OK
    

另外还支持在括号内使用-a-o表示and、or。

  • xuegao@LAPTOP-XUEGAO:~/temp/script$ if [ $a -gt 18 -a $a -lt 36 ]; then echo OK; fi
    OK
    

分支使用elifelse实现,下面是示例。

  • #!/bin/sh
    if [ $1 -lt 18 ]
    then
            echo "未成年人"
    elif [ $1 -lt 35 ]
    then
            echo "青年人"
    elif [ $1 -lt 60 ]
    then
            echo "中年人"
    else
            echo "老年人"
    fi
    

case 语句

语法

示例

  • #!/bin/sh
    
    case $1 in
    1)
            echo "one"
    ;;
    2)
            echo "two"
    ;;
    3)
            echo "three"
    ;;
    *)
            echo "other figures"
    ;;
    esac
    

for 循环

((;;))方式

语法

示例

for i in xx xx方式

语法(item array表元素数组)

示例

另外,shell支持{n..m}这种语法,下面是例子{1..100}表示从1到100的数组,所以下面的for循环会执行一百次。

  • xuegao@xuegao-PC:~/dev/workspace/script$ for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum
    5050
    

前面特殊变量章节提到过$@*、$@`,它俩也可以作为数组供给for循环使用。当加上双引号时,表现会所有不同。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat forIn.sh 
    #!/bin/bash
    
    echo '$*============================'
    for param in "$*"
    do
            echo $param
    done
    
    echo '$@============================'
    for param in "$@"
    do
            echo $param
    done
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./forIn.sh a b c 
    $*============================
    a b c
    $@============================
    a
    b
    c
    

while 循环

语法

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat while.sh 
    #!/bin/bash
    a=1
    sum=0
    while [ $a -le $1 ]
    do
            sum=$[ $sum + $a ]
            a=$[ $a + 1 ]
    done
    echo $sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./while.sh 100
    5050
    

这种夹杂着$和中括号写法实在是太丑陋了,但使用let关键字可以让写法优雅许多。

下面是使用let代码块,清爽得多,效果同上是一样的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat whileLet.sh 
    #!/bin/bash
    a=1
    sum=0
    while [ $a -le $1 ]
    do
            let sum+=a
            let a++
    done
    echo $sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./whileLet.sh 100
    5050
    

读取console输入

语法

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat read.sh 
    #!/bin/bash
    read -t 30 -p "你的称呼是:" name
    echo "欢迎$name使用本程序"
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ bash read.sh
    你的称呼是:雪糕
    欢迎雪糕使用本程序
    

函数

系统函数

basename

语法:basename <pathname> <suffix>

功能

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ basename ~/dev/workspace/script/shell/add.sh
    add.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ basename ~/dev/workspace/script/shell/add.sh .sh
    add
    

dirname

语法:dirname <pathname>

功能:去掉文件名,获取路径

示例(获取绝对路径

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dirname.sh 
    #!/bin/bash
    cd $(dirname $0)
    echo $(pwd)
    xuegao@xuegao-PC:~/temp$ bash ../dev/workspace/script/shell/dirname.sh 
    /home/xuegao/dev/workspace/script/shell
    

自定义函数

语法

注意

示例

归档文件

需求场景

脚本

  • #!/bin/bash
    
    #判断参数个数是否为1
    if [ $# -ne 1 ]
    then
    	echo 参数数量不为一个
    	exit
    fi
    
    #判断是否目录
    if [ -d $1 ]
    then
    	echo 
    else
    	echo 目录不存在
    	exit
    fi
    
    DIR_NAME=$(basename $1)
    DIR_PATH=$(cd $(dirname $1); pwd)
    
    #获取当前日期
    DATE=$(date +%y%m%d)
    
    #定义生成归档文件名称
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    DEST=~/temp/archive/$FILE
    
    #归档文件
    echo 开始归档……
    tar -czf $DEST $DIR_PATH/$DIR_NAME
    
    if [ $? -eq 0 ]
    then
    	echo 归档成功
    	echo 归档文件名为:$DEST
    else
    	echo 归档出错
    fi
    
    exit
    

使用crontab管理定时任务

  • 0 2 * * * /home/xuegao/dev/workspace/script/shell/dailyArchive.sh /home/xuegao/temp/archive
    

正则

常规匹配

在Linux中,grepsedawk文本处理工具,都支持通过正则表达式进行模式匹配

匹配文本,例如下匹配DIR_NAME字符串。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep DIR_NAME
    DIR_NAME=$(basename $1)
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    tar -czf $DEST $DIR_PATH/$DIR_NAME
    

使用^指定前缀匹配

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep ^if
    if [ $# -ne 1 ]
    if [ -d $1 ]
    if [ $? -eq 0 ]
    

$匹配后缀

  • if [ $? -eq 0 ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep gz$
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    

.匹配任意个字符

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep arch..e
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    DEST=~/temp/archive/$FILE
    

*不单独使用,和前个字符连用,表示前个字符出现任意次。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat helloShell.sh | grep Hel*
    echo "Hello $1"
    

技巧

常用特殊字符

字符区间[]:表示某个范围内的一个字符

特殊字符使用避免被转义,要注意使用的话,必须要将匹配文本使用引号包裹起来。下面是示例如何匹配$。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep "$1"
    if [ -d $1 ]
    DIR_NAME=$(basename $1)
    DIR_PATH=$(cd $(dirname $1); pwd)
    

下面是个匹配国内手机号的示例,其中grep添加-E参数表示支持regular expression扩展语法。({9}就是扩展语法,表示前面规则重复9次)

  • echo "13899889988" | grep -E ^1[3456789][0-9]{9}$
    

文本处理工具

cut

cut工作就是剪切负责剪切文件数据

语法

按空格分隔示例

-f参数支持同时提取多列

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cat note.txt 
    14      1       Lombok
    15      1       Jackson
    xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f 1,3 note.txt 
    14      Lombok
    15      Jackson
    

-f参数还支持-语法

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f -2 note.txt 
    14      1
    15      1
    xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f 2- note.txt 
    1       Lombok
    1       Jackson
    

awk

常规使用

强大的文本分析工具逐行读入,默认以空格为分隔符进行切片,再进行分析处理

语法

示例

拓展:BEGIN再所有数据读取之前执行,END在所有数据执行之后执行。

变量

使用-v参数

内置变量

  • FILENAME:文件名
  • NR:已读的记录数(行号)
  • NF:浏览记录的域个数(切割后,列的个数)

内置变量使用示例

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ awk '/sa..s/ {print "文件名:"FILENAME ",行号:"NR ",列数:"NF}' employee.txt 
    文件名:employee.txt,行号:3,列数:4
    文件名:employee.txt,行号:5,列数:4
    文件名:employee.txt,行号:6,列数:4
    文件名:employee.txt,行号:7,列数:4
    

综合应用案例

发送消息

利用Linux自带mesgwrite工具,向其他用户发送消息

需求

脚本

原文地址:https://blog.csdn.net/liangfenxuegao/article/details/129630923

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_25402.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注