010_shell编程 - llj2kh/studynote GitHub Wiki

shell 编程

1 注意事项

  • 赋值时“=”两边不能有空格,否则就是语法错误了。
  • Bash变量命名只能使用字母,下划线和数字,并且不能以数字开头。
  • 变量的引用有两种形式:
    • $var
    • ${var}
  • ' ' :单引号里的任何字符都会原样输出,单引号中对变量引用是无效的,且单引号中不能出现单引号(对单引号使用转义符也不行)
  • " ":双引号里可以引用变量,可以出现转义字符。
  • 使用 readonly 命令可以将变量限定为只读变量
  • 使用 unset 命令可以删除变量,但是不能删除只读变量。
  • Bash变量都是字符串。但是依赖于上下文,Bash也允许比较操作和算术操作。决定这些的关键因素是变量中的值是否只有数字,只有当变量是纯数字时,该变量才是“数字类型的”,否则就是字符串类型的。
  • Bash中的数字默认的是十进制,八进制需要以0开头,十六进制以0x开头。
  • 空变量+数字:数字变量
  • 未定义的变量+数字:数字变量
  • 局部变量(local variables):这种变量只有在变量所在的代码块或者函数中才可见,需要使用local声明;
  • 全局变量:Bash中用户自定义的普通变量默认是全局变量,可以在本文件中的其它位置引用;
  • 环境变量(environmental variables):所有的程序(包括shell启动的程序)都能访问环境变量。如果一个shell脚本设置了环境变量,需要用 export 命令来通知脚本的环境。

2 Bash的传参机制

shell通过位置参数(positional parameters)来给脚本文件传递参数,就是从命令行中传进来的参数,$0, $1, $2, $3... 其中:

  • $0 是该脚本文件的名字
  • $1 是第一个参数, $2 是第 2 个参数...
  • $9 以后就需要大括号了,如 ${10}, ${11}, ${12}...
  • $* 与 $@ 区别:
    • 相同点:都表示引用所有的位置参数;
    • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
$#	传递到脚本的参数个数  
$*	以一个单字符串显示所有向脚本传递的参数。  
$@	与$*相同,但是使用时加引号,并在引号中返回每个参数。  
$$	脚本运行的当前进程ID号  
$!	后台运行的最后一个进程的ID号  
$-	显示Shell使用的当前选项,与set命令功能相同  
$?	显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。  

3 Bash函数

  • 关键字function是可选的;
  • 函数定义必须在第一次调用前完成;
  • 在一个函数内嵌套另一个函数也是可以的,但是不常用.
  • 函数以位置来引用传递过来的参数(就好像他们是位置参数一样), 例如$1, $2, ...
  • 在函数调用之前,所有在函数内声明且没有明确声明为 local 的变量都可在函数体外可见(默认为全局变量)。
  • 如果变量用local 来声明,那么它只能在该变量声明的代码块中可见。这个代码块就是局部"范围"。在一个函数内,局部变量意味着只能在函数代码块内它才有意义。

4 Bash数组

  • Bash 只支持一维数组,用圆括号()来表示,数组元素之间用"空格"符号来分割
  • 初始化时不需要指定数组的大小。bash数组元素的下标从0开始。
  • 数组成员不必一定要连续,空缺元素是允许的;
  • 数组的一部分成员允许不被初始化, 没有被初始化的元素将打印空(NULL)值;
  • 访问数组元素的一般格式:
    • ${var[3]}
  • 遍历数组
    • 使用* 或@ 可以获取数组中的所有元素
    • ${var[*]}
  • 获取数组长度
    • ${#var[*]}

5 Bash字符串操作

  • ${string/#/abc}

在字符串前面添加abc

  • ${string/%/bac}

在字符串后面添加abc

  • ${!var[*]}
    获取数组的索引列表
  • 获取字符串长度
    • ${#var}
  • bash允许直接将字符串拼接在一起以获得新的字符串。
  • "#"表示从头匹配,%表示从尾匹配
  • 一个符号(#或者%)表示最短匹配,两个符号(##或者%%)表示最长匹配
${string:position}	在string中, 从位置position开始提取子串  
${string:position:length}	在string中, 从位置position开始提取长度为length的子串  
${string#substring}	从string的开头, 删除最短匹配substring的子串  
${string##substring}	从string的开头, 删除最长匹配substring的子串  
${string%substring}	从string的结尾, 删除最短匹配substring的子串  
${string%%substring}	从string的结尾, 删除最长匹配substring的子串  
${string/substring/replacement}	使用$replacement 来代替第一个匹配的$substring  
${string//substring/replacement}	使用$replacement 代替所有匹配的$substring  
${string/#substring/replacement}	如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring  
${string/%substring/replacement}	如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring