您的位置:首页 > 运维架构 > Shell

shell入门

2020-01-15 07:47 155 查看

shell入门

文章目录

  • 特殊变量
  • 运算
  • 条件判断
  • 流程控制
  • 读取控制台输入(read)
  • 函数
  • 常用的Shell工具
    • 查看当前使用的shell版本
    echo $SHELL

    hello world

    先新建一个helloworld.sh文件,在里面添加以下内容

    #!/bin/bash
    # 上面指明了脚本解释器,如果使用bash执行该脚本,那么这一行就是一条注释,但是如果通过 ./<文件名> 执行,该行就是一个解释器的声明
    # 即便是不写解释器声明,centos默认也是使用bash
    echo "hello world"

    然后返回,执行

    [alasky@localhost ~]$ bash helloworld.sh

    注意 此时不可以使用./<文件名>执行sh文件,会提示权限不够,但是使用root也不能执行,因为没有x权限,所以要加上x权限

    原因 使用bash可以执行,是因为我们对 /bin/bash 有执行权力,而bash对 .sh 文件有执行权力,所有我们通过bash就可以执行 .sh 文件,但是如果我们直接执行了 .sh 文件,就会因为没有 x 权限而失败

    [alasky@localhost ~]$ chmod +x helloworld.sh

    然后就可以使用 ./helloworld.sh执行了

    [alasky@localhost ~]$ ./helloworld.sh


    常用系统变量

    $HOME, $PWD, $SHELL, $USER

    • 查看当前系统中所有的变量
    set
    • 撤销(删除)变量
    unset <变量名>
    • $HOME 表示当前用户的家目录
    echo $HOME	#输出	/home/<用户目录名>
    • $PWD 表示当前目录
    echo $PWD	#输出	当前目录的绝对路径
    • $SHELL 表示当前使用的shell版本
    echo $SHELL	#输出	/bin/bash
    • $USERUSER 表示当前用户名称
    echo $USER	#输出	<用户名>


    自定义变量的声明

    注意

    1. shell里面只有字符串类型,所以不用声明变量类型,直接用就可以

    2. 定义变量时 = 两边不要加空格,如果变量的值有空格,需要将变量使用引号引起来

    3. 定义的变量作用范围只是当前的shell,如果新打开一个shell,那么自定义的变量就没有了

    定义普通变量
    [alasky@localhost ~]$ a=5	#这一行就相当于声明了一个变量
    [alasky@localhost ~]$ b=5
    [alasky@localhost ~]$ echo $a+$b	#打印变量,输出 5+5
    定义只读变量

    使用readonly定义的变量不能修改,也不能删除

    [alasky@localhost ~]$ readonly i=10
    [alasky@localhost ~]$ i=11	#会报错
    • 把当前shell的变量提升为全局变量,即在其他的shell中也能使用
    export <变量名>


    特殊变量

    • $n

    n为数字,$0代表该脚本名称,$1-9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如{10}

    举例 先创建一个sh文件

    [alasky@localhost ~]$ vim test1.sh

    然后在里面输入

    #!/bin/bash
    echo "$0  $1   $2"

    保存退出后,执行命令

    [alasky@localhost ~]$ chmod +x test.sh
    [alasky@localhost ~]$ ./test.sh 1 2 3	#输出	1 2 3
    • $#

    获取所有输入参数个数,常用于循环

    ****再创建一个test2.sh.在里面加入

    #!/bin/bash
    echo $#

    保存退出,添加x权限后,执行脚本

    [alasky@localhost ~]$ ./test2.sh 1 2 3 4	#输出 4
    • $* 和 $@

    KaTeX parse error: Undefined control sequence: \* at position 1: \̲*̲ 这个变量代表命令行中所有的参…*把所有的参数看成一个整体

    @这个变量也代表命令行中所有的参数,不过@ 这个变量也代表命令行中所有的参数,不过@这个变量也代表命令行中所有的参数,不过@把每个参数区分对待

    [alasky@localhost ~]$ vim parameter.sh
    
    #!/bin/bash
    echo "$0  $1   $2"echo $#
    echo $*
    echo $@
    
    [[alasky@localhost ~]$ bash parameter.sh 1 2 3
    parameter.sh  1   2
    3
    1 2 3
    1 2 3
    
    • $?

    最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确

    [alasky@localhost ~]$ ./helloworld.shhello world
    [alasky@localhost ~]$ echo $?
    0
    


    运算

    • 如果想要对定义的变量进行运算,就使用运算式
    [alasky@localhost ~]$ a=5
    [alasky@localhost ~]$ b=5
    [alasky@localhost ~]$ echo $[$a+$b]	#结果是10
    • 也可以使用expr定义,但是使用expr时,每个参数必须用空格隔开
    [alasky@localhost ~]$ a=5
    [alasky@localhost ~]$ b=5
    [alasky@localhost ~]$ expr $a + $b	#结果输出10


    条件判断

    语法

    [ <判断式> ] #注意判断式两边要有空格,判断式中判断符号的两边也要有空格

    返回结果 条件非空即为true,[ <字符串> ]也返回true;条件为空,即[] 返回false

    • 两个变量之间比较

      = 字符串比较
    [alasky@localhost ~]$ a=5
    [alasky@localhost ~]$ b=5
    [alasky@localhost ~]$ [ $a = $b ] #注意
    [alasky@localhost ~]$ echo $?
    • -lt 小于(less than)
    [alasky@localhost ~]$ [ 2 -ge 1 ]
    [alasky@localhost ~]$ echo $?
    0

    下面就不一一举例了

    • -le 小于等于(less equal)
      -eq 等于(equal)
    • -gt 大于(greater than)
      -ge 大于等于(greater equal)
    • -ne 不等于(Not equal)
  • 文件权限的判断

      -r 有读的权限(read)
    [alasky@localhost ~]$ [ -w helloworld.sh ]
    [alasky@localhost ~]$ echo $?
    0
    • -w 有写的权限(write)
    • -x 有执行的权限(execute)
  • 判断文件类型

      -e 文件存在(existence)
    [alasky@localhost ~]$ [ -e /home/alasky/helloworld.txt ]
    [alasky@localhost ~]$ echo $?
    1
    • -f 文件存在并且是一个常规的文件(file)

    • -d 文件存在并是一个目录(directory)



    流程控制


    if

    语法

    if [ 条件判断式 ]
    then
    程序
    fi

    或者

    if [ 条件判断式 ]
    then
    程序
    elif [ 条件判断式 ]
    then
    程序
    else
    程序
    fi

    注意

    1. [ 条件判断式 ],中括号和条件判断式之间必须有空格

    2. if后要有空格

    举例 新建一个iftest.sh文件,写一个简单的例子:判断输入的第一个参数的值

    [alasky@localhost ~]$ vim iftest.sh
    #!/bin/bash
    if [ $1 = 1 ]
    then
    echo "这是1"
    elif [ $1 = 2 ]
    then
    echo "这是2"
    else
    echo "我不知道这是啥"
    fi

    保存退出后,给新建的脚本添加权限

    [alasky@localhost ~]$ chmod +x iftest.sh

    测试

    [alasky@localhost ~]$ ./iftest 1
    这是1
    [alasky@localhost ~]$ ./iftest 2
    这是2
    [alasky@localhost ~]$ ./iftest 3
    我不知道这是啥

    case

    语法

    case $变量名 in
    "值1")
    如果变量的值等于值1,则执行程序1
    ;;
    "值2")
    如果变量的值等于值2,则执行程序2
    ;;
    *)
    如果变量的值都不是以上的值,则执行此程序
    ;;
    esac

    注意

    1. case行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束

    2. 双分号“;;”表示命令序列结束,相当于java中的break

    3. 最后的“*)”表示默认模式,相当于java中的default

    举例 使用case判断输入的第一个参数

    [alasky@localhost ~]$ vim casetest.sh
    #!/bin/bash
    case $1 in
    1)
    echo "这是1"
    ;;
    2)
    echo "这是2"
    ;;
    *)
    echo "我不知道这是啥"
    ;;
    esac

    测试省略


    for

    语法

    for (( 初始值;循环控制条件;变量变化 ))
    do
    程序
    done

    或者

    for 变量 in 值1 值2 值3…
    do
    程序
    done

    举例 打印1到99

    [alasky@localhost ~]$ vim fortest.sh
    #!/bin/bash
    for (( i=0;i<100;i++ ))
    do
    echo $i
    done

    while

    语法

    while [ 条件判断式 ]
    do
    程序
    done

    举例 打印1到99

    [alasky@localhost ~]$ vim whiletest.sh
    #!/bin/bash
    i=1
    while [ $i -le 100 ]
    do
    echo $i
    i=[ $i+1 ]
    done
    [alasky@localhost ~]$ [ -e /home/alasky/helloworld.txt ]
    [alasky@localhost ~]$ echo $?
    1
    [alasky@localhost ~]$ [ -e /home/alasky/helloworld.txt ]
    [alasky@localhost ~]$ echo $?
    1


    读取控制台输入(read)

    语法

    read [选项] [参数]

    选项

    ​ -p <提示语> 指定读取值时的提示语

    ​ -t 指定读取时等待的时间(秒)

    参数

    ​ 指定读取的变量名

    举例 写一个shell脚本,让用户在控制台输入一个姓名,并返回“姓名+你好”

    [alasky@localhost ~]$ vim readtest.sh
    #!/bin/bash
    read -p "请输入姓名" name
    echo $name"你好"
    [alasky@localhost ~]$ chmod +x readtest.sh
    [alasky@localhost ~]$ ./readtest.sh
    请输入姓名alasky
    alasky你好


    函数

    系统函数举例
    • basename

    basename命令会删除文件路径的所有前缀,只输出文件名,如果指定了后缀,还会将后缀删除

    语法:

    basename <文件路径> [后缀名]

    举例

    [alasky@localhost ~]$ basename /home/alasky/readtest.sh
    readtest.sh
    [alasky@localhost ~]$ basename /home/alasky/readtest.sh .sh
    readtest
    • dirname

    从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)

    语法:

    dirname <文件路径>

    举例

    [alasky@localhost ~]$ dirname /home/alasky/helloworld.sh
    /home/alasky


    自定义函数

    语法

    [ function ] funname[()]
    {
    Action;
    [return int;]
    }
    funname

    注意

    1. 调用函数的语句必须写在函数声明之前,因为shell是解释性语言,从上到下执行,如果在函数声明之前调用函数,会报错

    2. 声明函数的关键字

    function
    和函数的参数列表
    ()
    可以省略,但是只能省略一个,不能同时省略

    _3. 函数可以定义返回值,但是函数的返回值返回的不是数值,而是函数的执行状态(是否执行成功),_函数返回值,只能通过$?系统变量获得,可以显示加

    return
    返回,如果不加,将以最后一条命令运行结果,作为返回值;return后跟数值n(0-255)

    举例 定义一个函数,计算两个输入参数的和,并执行该函数

    [alasky@localhost ~]$ vim funtest.sh
    #!/bin/bash
    function sum()
    {
    s=0
    s=$[ $1 + $2 ]
    echo "$s"
    }
    
    read -p "输入第一个数: " n1;
    read -p "输入第二个数: " n2;
    sum $n1 $n2;
    [alasky@localhost ~]$ chmod +x funtest.sh
    输入第一个数: 1
    输入第二个数: 2
    3


    常用的Shell工具

    注意 以下举例的常用命令,都是可以直接写在sh脚本文件里的,方便起见,这里就直接写在命令行模式下了


    cut

    管道工具,用来剪切部分数据

    语法

    cut [选项] [文件名]

    选项

    ​ -f 列号,提取第即列

    ​ -d 分割符,按照指定分隔符分割

    ​ -c 指定具体的字符

    举例1 首先创建一个文件作为剪切的文件,分别剪切第1列和第2,3列

    [alasky@localhost ~]$ vim cuttest.txt
    one1 one2 one3
    two1 two2 two3
    three1 three2 two3
    four1 four2 two3

    使用cut提取文件的第一列

    [alasky@localhost ~]$ cut -d " " -f 1 cuttest.txt
    one1
    two1
    three1
    four1

    使用cut提取文件的第二列和第三列

    [alasky@localhost ~]$ cut -d " " -f 2,3 cuttest.txt
    one2 one3
    two2 two3
    three2 two3
    four2 two3

    举例2 提取出ip addr命令打印出来的ip地址(提取ip信息的指令因linux系统而异,出不来结果不要着急,自己摸索一下就好)

    [alasky@localhost ~]$ ifconfig eth0 | grep "inet addr" | cut -d: -f 2 | cut -d" " -f 1
    192.168.0.105

    sed

    sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出

    语法

    sed [选项] ‘[命令]’ <文件名>

    注意 sed命令只是在缓冲区修改文本内容,实际的文件内容并没有改变!

    选项

    ​ -e 直接在指令列模式上进行sed的动作编辑

    ​ -i 直接编辑文件

    命令

    ​ na <添加的内容> 追加,n表示第几行,a表示在n的下一行插入添加的内容

    ​ d 删除

    ​ s 查找并替换

    举例1 将”three1 three2 three3”插入到第2行后面并打印

    创建一个新的文件

    [alasky@localhost ~]$ vim sedtest.txt
    one1 one2 one3
    two1 two2 two3
    four1 four2 four3

    执行命令

    [alasky@localhost ~]$ sed '2a three1 three2 three3' sedtest.txt
    one1 one2 one3
    two1 two2 two3
    three1 three2 three3
    four1 four2 four3

    注意 ! 虽然打印出来是添加了three那一行,但是实际上文件并没有改变

    [alasky@localhost ~]$ cat sedtest.txt
    one1 one2 one3
    two1 two2 two3
    four1 four2 four3

    举例2 删除刚刚创建的sedtest.txt下包含four的行

    [alasky@localhost ~]$ sed '/four/d' sedtest.txt
    one1 one2 one3
    two1 two2 two3

    注意 这个文件仍旧没有改变

    举例3 替换第三行为”three1 three2 three3”

    [alasky@localhost ~]$ sed 's/four/three/g' sedtest.txt
    one1 one2 one3
    two1 two2 two3
    three1 three2 three3

    awk

    把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理

    语法

    awk [选项] '内容1{操作1} 内容2{操作2}...内容n{操作n}' <文件名>

    选项

    ​ -F 指定输入文件的分隔符

    ​ -v 赋值一个用户定义变量

    举例 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割

    [alasky@localhost ~]$ sudo cp /etc/passwd ./
    [alasky@localhost ~]$ awk -F : '/^root/{print $1","$7}' passwd
    root,/bin/bash

    sort

    将文件进行排序,并将排序结果标准输出

    语法

    sort [选项] <文件名>

    选项
    -n 依照数值的大小排序

    ​ -r 逆序

    ​ -t 设置排序时所用的分隔符

    ​ -k 指定需要排序的列

    举例 创建一个文件,按照文件内容的第二列逆序排序

    [alasky@localhost ~]$ vim sorttest.txt
    小明:1:18:1199834
    小红:2:34:8970389
    小刚:3:21:3123478
    [alasky@localhost ~]$ sort -t : -nrk 2 sorttest.txt
    小刚:3:21:3123478
    小红:2:34:8970389
    小明:1:18:1199834

    o1 two2 two3
    three1 three2 three3

    
    ##### awk
    
    把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理
    
    **语法**
    
    ```bash
    awk [选项] '内容1{操作1} 内容2{操作2}...内容n{操作n}' <文件名>

    选项

    ​ -F 指定输入文件的分隔符

    ​ -v 赋值一个用户定义变量

    举例 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割

    [alasky@localhost ~]$ sudo cp /etc/passwd ./
    [alasky@localhost ~]$ awk -F : '/^root/{print $1","$7}' passwd
    root,/bin/bash
    sort

    将文件进行排序,并将排序结果标准输出

    语法

    sort [选项] <文件名>

    选项
    -n 依照数值的大小排序

    ​ -r 逆序

    ​ -t 设置排序时所用的分隔符

    ​ -k 指定需要排序的列

    举例 创建一个文件,按照文件内容的第二列逆序排序

    [alasky@localhost ~]$ vim sorttest.txt
    小明:1:18:1199834
    小红:2:34:8970389
    小刚:3:21:3123478
    [alasky@localhost ~]$ sort -t : -nrk 2 sorttest.txt
    小刚:3:21:3123478
    小红:2:34:8970389
    小明:1:18:1199834
    • 点赞
    • 收藏
    • 分享
    • 文章举报
    Alaskyed 发布了24 篇原创文章 · 获赞 3 · 访问量 1044 私信 关注
  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: