原创

shell(一)

基本使用

执行shell脚本 文件后缀为 .sh ,Linux下的shell解释器众多,如Bourne Shell 和 Bourne Again Shell所代表的的/bin/sh和/bin/bash,但也无需分的太清楚。一般在行首使用#!bin/sh来指定解释器。echo 表示向窗口输出文本/打印
file

编辑完成后可对文件做个chmod权限控制,根据自己需要添加就行了。使用/bin/sh运行文件即可

./test.sh       #加./ 指定路径 ,教程说一定要加,但其实不加好像也没什么关系

备注:权限设置之数字表示法
三种权限分别是可读(r)、可写(w)、可执行(x),使用八进制数分别代表4、2、1。linux下文件权限表共10位,除了表示文件类型的第一位,后九位分为三组,其意义分别为:文件拥有者、系统群组、系统其他用户

如设置某文件给系统拥有者为可读/写/执行,群组可读/执行,其他用户可执行。则该文件权限为:-rwxr-x--x 按照数字对应即为:751

Shell变量

  • shell赋值变量的规则大抵和其他语言类似,唯一注意的是变量名和等号之间不能有空格。

  • 使用变量只需在变量名前加$符,最好在变量名外添加一个识别变量边界的花括号。如:echo ${name}

  • 只读变量不可更改,也不可被unset删除。从这里看出shell是逐行运行的,前面正常的代码还是会正常输出

file
file

但是也同样发现一个问题,当变量被unset后,此时使用readonly定义一个已经被删除的变量名后打印出来,会出现一个打印了空白行的效果(也可能是回车了)
file
file

而变量被unset并readonly后,重新对已删除的变量名进行重新赋值,则继续报变量名已读的错误
file
file

对此目前我的理解是unset只是给原变量更换了新的空白值,并没有真正把name整个变量删除掉。所以才会导致当我添加readonly后继续输出会显示一个空白行。

  • 变量类型

    局部变量;在脚本或命令中定义。当前脚本有效
    环境变量;所有程序都可访问,部分程序依靠环境变量来运行
    Shell变量;保证Shell正常运行的变量

Shell字符串

  • 字符串使用单/双引号

    • 单引号是原样输出引号内所有字符串,故不可在单引号内使用变量,也不可使用转义。
    • 双引号则相反,可使用双引号也可以使用转义
  • 字符串长度获取

    ${#str} 得到变量str字符串长度(包含首尾空格)
    
  • 字符串截取

    ${str:frist:last} 获取字符串从first(含)开始到last(含)结束的子串。
    
  • 查找子串位置

    ·expr index "$str" ab·   获取ab子串在变量str中的位置,注意expr外面是反引号。
    

    需要注意的是,子串位置是从1开始计算,而字符串截取是从0开始计算。查找子串时,首先会查找“ab”串是否在变量中存在,若存在则返回该子串首次出现位置,不存在则反馈“a”串在str中的首次出现位置

Shell数组

shell只有一维数组,并且大小不受限制。唯有下标与其他语言的数组是同步的——从0开始。允许下标不连续,大小也无限制。

  • 数组的创建
    arr=(v1 v2 v3…)
    
  • 数组的读取

    arr{[n]}   读取追的指定下标,当指定的元素
    arr{[@]}   读取数组所有元素
    
  • 数组长度

    length=${#arr[@]}   数组总长
    length=${#arr[n]}   指定数组元素长度
    

注释

单行注释使用#
多行注释使用:< < EOF +EOF配合使用

传递参数

在linux 下执行脚本时,需保证该脚本是否有可执行权限。执行脚本例如:

./test.sh p1 p2 p3 … pn代表参数
代码中引用参数时,$0代表当前文件名称,$1才代表第一个参数,以此类推……

当需要精准地根据位置填入参数时,建议使用单引号将参数括起来。

$ * 与 $@

  • $ * 将其视为一个参数传递传入:
    file
    file

  • $@则将其视为三个参数分批传入
    file
    file

运算符

原生bash不支持运算符,但一般用命令(如expr)实现

  • 算数运算符
    val=expr 1 + 1 加号两边必须带空格,否则直接输出"1+1"
    val=expr 2 \* 1 乘法前面需要加个反斜杠转义
    val=expr=2 / 6 除法结果只能为正整数,最小为0,去掉小数
    val = $a 赋值, 将变量a的值赋给val
    [ 2 == 6 ] 比较,相等时得 1,不相等得 0
    注意:比较双方左右必须有空格,算数运算符支持数字和变量

  • 关系运算符
    -eq:判断相等 相等则返回ture
    -ne:判断不相等,不相等返回ture
    -gt:判断大于,大于则返回ture
    -lt:判断小于,小于返回ture
    -ge:判断大于等于,是则返回ture
    -le:判断小于等于,是则返回ture

  • 布尔运算
    !:非。结果为T返回F,为F返回T
    -o:或。其中一边为T则为T,都为F才返回F
    -a:与。两遍均为T才返回T,否则返回F

  • 逻辑运算符
    &&:and,即上面的-a
    ||:or,即上面的-o

  • 字符串运算符
    = 检测字符串是否相等 相等返回T
    -z 字符串长度是否为0 0返回T
    -n 字符串长度是否不为0,不为0返回T
    $ 判断字符串为空 空返回T

  • 文件检测运算符
    -r 是否可读 | -w 是否可写 | -x 是否可执行 | -f 是否为普通文件
    -d 是否为目录 | -s 判断文件是否非空 | -e 判断文件是否存在

Shell 输出命令

  • echo
    echo后的双引号可加可不加
    转义字符: \ 。转义需要使用echo -e开启
    输出结果定向至指定文件夹: >文件名
    输出日期 echo dete date使用反引号括起
  • printf
    模仿的是C语言中的printf(),使用printf的脚本比echo的移植性好。printf一般用于格式化输出,指定字符串间距、对齐方式等
    例如:printf "%-10s %-8s %-4s\n" "%-4.2f"
    %-10s:指定一个宽度为10的字符串长度,-表示左对齐,所有字符都会显示在这个宽度里
    %-4.2f:将格式转化为小数,整数+小数共4位且小数保留两位

Shell test命令

  • 文件测试
    test一般用于检查谋而条件是否成立,可比较字符、数值、文件三个方面的测试
    -e:文件存在即为真
    -r:文件存在且可读为真
    -w:文件存在且可写为真
    -x:文件存在且可执行为真
    -s:文件存在且至少有一个字符为真
    -d:文件存在且是一个目录为真
    -f:文件存在且为普通文件为真

Shell 流程控制

  • 分支

    if ……
    then 
      ……
    elif ……
    then
      ……
    else  ……
    then
      ……
    fi
    

    也可写成同一行,使用分号将不同的语句端隔开。一般用在终端命令提示符

    if ……  ; then ……; elif …… ; then …… ;else ……; then ……; fi
    
  • for循环
    in 列表可包含文件名、字符串等

    for var in v1 v2 v3 …
    do 
      ……$var ……
    done
    

    同样可写成一行,使用分号隔开语句:
    for var in v1 v2 v3 …; do …… ; done

  • while循环
    与for 循环类似,格式如下

    while ……
    do 
      ……
    done
    

    除了基本的循环,while还支持通过read 读取键盘输入的信息:
    while read var
    do
    ……$var……
    done
    :在控制条件时,a=expr $a + 1let "a ++"的想过是相同的,但是let命令比前者运行速度更快,但是使用expr的兼容性更好一些

  • until 循环
    与while类似,只是刚好相反,当判断条件为ture时停止循环

    until  ……
    do
      ……
    done
    
  • case esac分支
    value可取变量或常量。模式后必须跟)。一旦匹配成功,运行其中所有代码直至;;处。若无匹配到,则进入*模式运行其中代码。该模式还支持正则表达式匹配
    ```
    case value in
    value1)
    ……
    ;;
    value2)
    ……
    ;;
    value3)
    ……
    ;;
    *)
    ……
    ;;

esac
```

Shell 函数

  • 格式
    [ function ] funName [ ( ) ]
    {
    方法体;
    ……$1……
    ……$2……
    ……$3……
    ……
    ……${10}……
    ……$11{}……
    ……
    return [ int 0~255; ]
    }
  • 注意

    可使用function fun()或直接fun()无参定义。调用函数直接写函数名即可
    返回值:返回值只能是数值,且范围是0~255。(教程说若无return 语句则最后一句作为返回值。实测后并不是,而是返回0)
    函数外返回值调用时使用$?
    参数调用时使用$n,当n>=10则必须使用${n}

重定向

  • 输出重定向
    通过>(覆盖原内容) 或 >>(追加原内容)重定向至指定文件,格式:
    command1>file1

将echo标准输出的终端重定向为user文件
file

输出重定向会将原内容覆盖,若不想覆盖则使用>>进行追加
file
file

  • 输入重定向
    一般使用输入重定向是想要对文本内容进行统计,使用linux的wc命令即可统计文本
    wc [-c 字节数]/[-w 单词数]/[-l 行数] [文件名]

file

也可使用while逐行读取全部内容

file
file

>>表示使用指定分界符作为命令输入结束的标志,只有输入分界符后才结束内容读取。使用情况如下:

file

同时将输入/输出重定向,将echo输出的文本加上 user文件本身的内容一起读取后追加至new文件里

file

文件包含

在sh文件内部可调用外部sh脚本,便于封装一些公用代码作为独立文件,被调用的文件可无需执行权限

  • 调用方式
    . filename 注:点号后有空格
    source filename
    file
    file
正文到此结束