shell语法

一门新的语言

Linux中常见的脚本

  1. sh:/usr/bin/sh或/bin/sh
  2. bash:/bin/bash
  3. csh:/usr/bin/csh
  4. ksh:/usr/bin/ksh
  5. zsh

    开头必须使用 #! /bin/bash指名bash为脚本解释器

    运行方式:

    作为可执行文件:

  6. chmod +x test.sh使脚本具有可执行权限
  7. ./test.sh当前路径下执行(相对路径)
  8. /home/acs/test.sh绝对路径下执行
  9. ~/test.sh家目录下执行

    用解释器执行

  10. bash test.sh

    echo

  11. 意思和c++中cout 或 printf相同

    注释

  12. 井号后面的都是注释,(与py相同)
  13. 其实脚本解释的时候#! /bin/bash解释的时候也是注释,只是系统识别为脚本解释器
  14. 多行注释:前 :<<EOF后:EOF;其中EOF也可以换成其他字符串,或者符号(必须首位相同)

    变量

    变量的定义

  15. 定义变量不需要¥符号
  16. name1=’yxc’ (单引号定于字符串)
  17. name2=”yxc” (双引号定义字符串)
  18. name3=yxc (可以不加引号,同样表示字符串)
  19. 注意等号两边不能有空格!!!否则会报错

    使用变量

  20. 使用变量需要加上¥(此符号在bash中意为取值),或者$(),花括号是可选的,主要是为了帮助解释器识别边界
  21. echo $yxc
  22. echo $(yxc)
  23. echo会自动换行
  24. 错误:echo $namesacwing,因为没有括号,边界判断不对,不知道是namesacwing还是names

    只读变量

  25. readonly 变量(相当于c++中的const,声明了一个只读变量)
  26. declare -r 变量

    删除变量

  27. unset(类似于c++终端undef),如果一个变量被删除,后面调用的时候会替换为空(NULL)

    变量类型

  28. 自定义变量(局部变量):子进程不能访问的变量
  29. 环境变量(全局变量):子进程可以访问的变量

    自定义变量转环境变量

  30. export 变量名
  31. declare -x 变量名
  32. 此时可以在子进程中使用变量

    使用bash

  33. 使用bash会将原进程bash睡眠掉,进入一个新的bash子进程
  34. 退出:exit或者ctrl+d

    环境变量转自定义变量

  35. declare +x 变量名(可以理解为给变量赋予了自定义权限)

    字符串

  36. 字符串可以使用单引号,也可以使用双引号,也可以不使用引号

    单引号和双引号的区别(不加引号和双引号相同)

  37. 单引号中的内容会原样输出,不会执行,不会取变量(即不会转义),即没有使用&符号取值
  38. 双引号中的内容可以执行,可以取变量,即可以使用&取值

    取出字符串的长度

  39. ¥后面加井号
  40. echo ${井号name},即可以取出name的长度(注意这个地方是花括号)

    提取子串

  41. 根据下标取值
  42. echo ${name:m:n}注意这个每一个下标前都有冒号

    查看自己开了多少进程

  43. top可以查看
  44. 按下退出

    文件参数变量

  45. 在执行shell脚本时可以想脚本传递参数,$1时第一个参数,$2是第二个参数…,特殊的是$0是文件名(包含路径)
  46. $#:文件传入参数的个数(不包括文件名)
  47. $*:由所有参数构成的用空格隔开的字符串,整体为字符串用双引号括起来
  48. $@:每个参数分别用双引号括起来的字符串(@和*都是取所有的意思)
  49. $$:脚本当前运行的进程ID
  50. $?:上一条命令的退出状态(注意不是stdout,而是exit code),0表示正常退出,其他值表示错误
  51. $(command):返回command这条命令的stdout(注意区分stdout和exit code,输出的数是stdout,例如cout,而退出状态是exit code,例如c++中的return)
  52. command 返回command这条命令的stdout,(~上面的`)(7,8等价)

    $()小括号是获取stdout的值,${}是取变量的值

    数组

  53. 数组中可以存放多个不同的值,只支持一位数组,初始化时不需要指定数组大小(和py中的list一样不需要指定数组大小)

    定义

  54. 数组用小括号表示,元素之间用空格隔开,如:array=(1 abc “def” yxc)
  55. 也可以直接定义数组中某个元素的值,如:array[0]=1,array[1]=abc,array[2]=”def”

    读取数组中某个元素的值

  56. 格式:${array[index]}
  57. echo ${array[0]}

    读取整个数组

  58. 格式:(@和*都是取所有的意思)
  59. $(array[@])
  60. $(array[*])

    expr命令

  61. 格式:expr 表达式
    ####说明:
  62. 用空格隔开每一项
  63. 用反斜杠放在shell特定的字符前面,发现表达式运行错误时,可以试试转义
  64. 包含空格和其他特殊字符的字符串要用引号括起来
  65. expr会在stdout中输出结果,如果结果为真,stdout为1,否则为0
  66. expr也有exit code返回值,如果为真,exit code为0,否则为1
  67. stdout 和 exit code 返回值为互反(真时相反,假时也相反)

    字符串表达式(以下参数都是在expr后面的)

  68. 输出长度:length STRING:返回STRING的长度
  69. index STRING CHARSET:CHARSET中任意单个字符在STRING中最前面的字符位置,下标从1开始。如果子啊STRING中完全不存在CHARSET中的字符,则返回0
  70. substr STRING POSITION LENGTH 返回STRING字符串中从POSITON开始,长度最大为LENGTH的子串。如果POSITION或LENGTH为负数,0或非数值,则返回空字符串(下标从1开始)  

    整数表达式

  71. expr支持普通算数操作,算数表达式优先级低于字符串表达式,高于逻辑表达式
    • — 加减运算,两端参数会转化为整数,如果转化失败则会报错
  72. * / % 乘除取余运算,两端参数会转化为整数(*在shell中有特殊含义,所以需要转义)
  73. ()可以表示优先级,但是需要用反斜杠转义

    逻辑表达式

  74. | 或(c++中是||,少一半):如果第一个值不是0,则会返回第一个值,第二个值不会计算,如果第一个参数非空并且非0,则会返回第一个参数的值
  75. & 与 (c++中是&&,少一半):如果第一个值是0,则不会计算第二个值(短路特性),如果都非空并且非0,则会返回第一个值
  76. == 与 = 是同义词,但是还是要按照c++来写逻辑等号==,复制=
  77. < <= > >= != == = 比较两端的参数,如果为true则返回1,否则返回0,expr首先尝试将两端的参数转换为整数,并做算数比较,如果转换失败,则按字符集排序规则做字符比较(strcmp)
  78. 需要转义的:*、()、>、<=、|、&
  79. echo expr a + b加号和数字之间有空格
                                                                                                                                                                                                                                                                                                                                                                                                                                                           ### read命令(cin或scanf)
    
  80. 用于从标准输入中读入单行数据,当读到文件结束符时,exit code为1,否则为0
  81. -p 添加提示信息(类似于input(提示信息))
  82. -t 后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令

    echo命令(相当于cout或printf)

  83. 输出格式:echo STRING
  84. 显示普通字符串:echo “Hello acterminal”,引号也可以省略
  85. 显示转义字符:echo “"Hello acterminal"“注意只能使用双引号,单引号不能够转义
  86. 也可以省略最外面表示字符串的双引号:echo "Hello acterminal"
  87. 显示变量:注意一定要用双引号,单引号不能够转义:name=yxc echo “My name is $name”
  88. 显示换行:直接\n无法显示换行转义,开启转义需要-e:例如:echo -e “Hi\n”,即可输出转义
  89. 强行不换行:-e后\c,\c可以取消最后的回车(和py中的end = “”相同),因为echo和py中的print相同,最后会自动换行。
  90. 显示结果到echo “Hello world” > output.txt
  91. 原样输出字符串,不进行转义或取变量:用单引号引起来
  92. 显示命令的执行结果:用`引起来

    printf语句(c++中是以,隔开每一项,而shell中是以space隔开每一项)

  93. 格式:printf format-string [arguments…]
  94. printf “%d\n” yxc
  95. shell中printf不自带换行,所以需要自己加上\n(此时无需-e进行转义)

    文件逻辑运算符

  96. |与&单与和单或是expr中的(必须在expr中使用)
  97. 而||与&&双与和双或是bash中自带的,可以直接在bash中使用
  98. 也带有短路特性
  99. 表达式中的exit code为0表示真,非0表示假
  100. 可以根据短路特性来做if表达式

    test命令

  101. test命令用于判断文件类型,以及对变量做比较
  102. test命令用exit code来返回结果,而不是使用stdout,0表示真,非0表示假
  103. test -e test.sh && echo “exist” || echo “Not exist”这种情况,如果前面test判断为0(真就会执行逻辑与(虽然是0,但是也是真,这种情况下可以不去看是0还是1,直接根据真假判断))

    文件类型判断

  104. -e文件是否存在(exist)
  105. -f是否为文件(file)
  106. -d是否为目录(directory)

    文件权限判断

  107. -r文件是否可读
  108. -w文件是否可写
  109. -x文件是否可执行
  110. -s文件是否为非空文件,是则返回0(真),否则返回1(假)

    整数间的比较

  111. -eq a是否等于b(equal)(为什么不是-e,因为-e是转义,已经被使用过,-e也可以是exist中的是否存在)
  112. -ne a是否不等于b(not equal)
  113. -gt a是否大于b(great test)
  114. -lt a是否小于b(less test)
  115. -ge a是否大于等于b(great or equal)
  116. -le a是否小于等于b (less or equal)

    注意区分expr和test

  117. expr是stdout,1表示真,0表示假(就和if一样,if内部是1即为真)
  118. test是exit code,0表示真,非0表示假(就和return一样,return 0即为真,return 一个非0的值即为假)

    字符串比较

  119. -z判断STRING是否为空,如果为空则返回true
  120. -n判断STRING是否为非空,如果为非空则返回true(-n也可以省略)
  121. == 判断s1和s2是否相等
  122. !=判断s1和s2是否不相等
  123. >和<判断(需要用反斜杠转义),结果等于使用strcmp(逐个字符的ascii码进行比较)

    多重条件判定

  124. 命令格式:test -r filename -a -x filename(由2,3条来链接两个test命令,第二个命令不需要test)
  125. -a:&&,and
  126. -o:||,or
  127. !:例如test ! -x filename:当filename不可执行时,返回true

    判断符号

  128. 【】和test用法几乎一样,更常用于if语句中
  129. []内的每一项都要用空格隔开
  130. 中括号内的变量,最好用双引号括起来(为了防止当变量中有空格时&取值出现错误(too many arguments))
  131. 中括号内的常熟,最好用单或双引号括起来

    判断语句

  132. if then语句,(类似与c++中的if-else语句)if后面跟的是命令,不是值
  133. if expr 3 \< 3和if 0相同,但是0不是命令,所以无法执行
  134. 需要写if后面跟着命令 if expr 3 < 3
  135. if then elif then else fi
  136. case $变量 in 值1)…;;值2)…;;*)…;; esac