0 注意点:
1. 空格! 因为shell 中空格是作为一个分隔符来判断命令 参数之间的关系的,所以很多地方要注意空格; 2. 变量: 变量名: 下划线 字母 数字(不可以是开头) 变量类型 : 统一按照字符串处理, 后面根据变量操作而变换类型 3. 函数定义: 下面会有一些符号意义: $()和`` 是一组他在shell 中表示的是 命令的替换,就是在shell 中fork 一个子进程 区做 他们 括起来的命令 然后在返回父进程。 特别要注意的是在有system 调用的地方要放这种command的内嵌,是黑客攻击的对象。需要字符串化或者转义,但有一点要注意转义后就不要再字符符串化了。 ${} 变量替换 就是把变量的真实值带入。 $[]和$(()) 是一组 标识的是 算术运算 +-*/ ,下面有示例将某个变量值进行计算; 还有种方式: let cnt++ [ ] 是test 的另一种格式 注意左右需要空格。 [[ ]] 是加强的[] 可以有匹配 没有字符的分割。if等条件判断中会使用到; (()) 是一种可以支持数学运算符的 条件判断, 可当作 [] 用,只要其中的表达式符合c就可以。他和[[]]的区别是,(())可以支持 +-*/ 而[[ ]] 支持 匹配;
1. 基本格式 与 调试操作:
#!/bin/bash #这是用来注释 echo "hello shell! current path is " pwd ls -al
a. 上面的示例中 #!/bin/bash 定义了解释器, 注释 通过 # 实现;
b. 调试有两种方式;一种是在脚本编写中开启/关闭调试; 另一种是在调用过程中开启调试(bash -x);
脚本中增加调试步奏:
脚本运行中通过bash -x 方式实现调试开启(其中+行就是脚本内容,下面是执行的结果)
2. 变量定义: shell变量是一种弱类型变量,不需要定义变量的类型;
局部变量:local a = 12
全局变量: 没有局部定义的关键字(local),就是全局变量
其他注意点参考下面示例:
#!/bin/bash a=12 #定义中间不能有空格, a = 12 是错误的; echo ${a} #使用变量时候,必须要有$, 最好再用${a} b="hello, world!" #定义字符串时,有空格需要使用“” echo ${b} c=`pwd` #可以使用命令的返回为值; echo ${c} d=$a:a echo ${d}
常见的特殊变量:
$0 : 获取当前执行shell 脚本文件名,包含路径; $n : 获取当前执行脚本的第n 个参数,n = 1... , 如果n > 9, 则需要将n 使用大括号括起来${12} $* : 获取当前shell 的所有参数,将说有命令行参数视为单个字符串,相当于“$1$2$3" $@ : 获取这个程序所有的参数,并保留参数之间的任何空白,相当于”$1" "$2" "$3", 这是将参数传给其他程序的好办法 $# : 得到执行当前脚本的参数个数 $? : 判断上一指令是否执行成功,0 成功, 非0 失败 $$ : 取当前进程的PID $! : 上一个指令的PID
a=/dir/path/folder/link/filename.txt.log #非贪婪匹配(最小匹配)左删除 echo ${a#*/} echo ${a#*.} #非贪婪匹配(最小匹配)右删除 echo ${a%*/} echo ${a%*.} #贪婪匹配左删除 echo ${a##*/} echo ${a##*.} #贪婪匹配右删除 echo ${a%%/*} echo ${a%%.*}
#shell字符串提取字串 echo ${a:5:6} #提取左边第5个字符往右的6个长度的字节内容 #字符串中变量值的替换 ${a/f/F} #替换第一个f ${a//f/F} #替换所有的f #${} 可以针对不同的状态(没设定,空值,非空值)进行赋值 ${a:-my_file.txt} : 如果${a} 没有设定或为空值,则可以返回my_file.txt 类似的还有 (- :- = := + :+ ? :?) 等一系列的
3.输入输出
read [-option] -[variable...] -a array : 把输入赋值到数组array 中,索引从0 开始 -d delimiter : 用字符delimiter 中第一个字符指示输入结束,而不是一个换行符 -e readline 使用readline 来处理输入,使得与命令行相同的方式编辑输入; -n num 读取num 个输入字符,而不是整行 -p prompt : 为输入显示提示信息,使用字符串prompt -r raw mode : 不把 反斜杠 \ 字符解释为转义字符 -s silent mode : 不显示输入 -t seconds : 超时 -u fd : 使用文件描述符 fd 中的输入,而不是标准输入;
echo : echo string
-n : 删除默认换行
-e : 开启转义
printf : printf format-string [arguments...]
printf "%s is %d years old\n" Xiaoming 18
0: standard input(STDIN) 1: standard output(STDOUT) 2: standard error ouput(STDERR) 我们可以通过< 来改变读进的数据信道,还可以通过> 改变送出的数据到指定的文件中 ls newa* 1 1>file.out 2>file.err #将STDOUT 保存到file.out 文件中,错误保存在file.err 文件中
4. 函数
有下面三种定义函数方式,注意区分函数中的${1} 与 全局中 ${1} 之间的差别
#!/bin/bash #三种定义函数方式 function __func1__() { echo "$1" #只能是当前函数的参数,可以将全局的${1} 传进来 return 123 } function __func2__ { echo ${1} return 234 } __func3__() { echo ${1} return 345 } __func1__ var1 var2 __func1__ ${1} ${2} #这里的$1 与 __func1__ 中的$1 不一样,注意区分 echo $? __func2__ var1 var2 __func2__ ${1} ${2} #这里的$1 与 __func1__ 中的$1 不一样,注意区分 echo $? __func3__ __func3__ echo $?
5. 流程控制 IF /case
if:
要用双中括号(功能比单中括号 更强大),前后必须有空格;以fi 结尾
man test 中显示各类比较方式,可以作为condition 表达式
#!/bin/bash if [[ condition ]]; then #要用双中括号(功能比单个中括号 更强大),前后必须有空格; #statements fi #以fi 结尾 if [[ condition ]]; then #statements else #statements fi if [[ condition ]]; then #statements elif [[ condition ]]; then #statements elif [[ condition ]]; then #statements else #statements fi
注意下面用法: \$[\${1} % 2] : $[] 用来计算整数表达式的值,只能整数计算
#!/bin/bash for i in `ls -A`; do echo ${i} done read start end for i in `seq ${start} ${end}`; do if [[ $[${i} % 2] -eq 0 ]];then echo ${i} fi done
case :
#!/bin/bash case word in pattern1 ) ;; #类似C 中break; pattern2 ) ;; pattern3 ) ;; esac #结束的标志
#!/bin/bash read num flag=$[ ${num} % 2 ] case ${flag} in 0 ) echo "even" ;; 1 ) echo "odd" ;; esac
6. 循环
for 循环:
for i in words; do #for i in `seq ${start} ${end}`; do #for i in `ls -A`; do #for i in a b c d e; do #for i in 1 2 3 4 5; do #statements done for (( i = 0; $i < 6; i++ )); do #statements done
#!/bin/bash cnt=0 function __count__() { for i in `ls -A ${1}`; do if [[ -f $1/$i ]]; then #这里的文件要给绝对路径 let cnt++ echo ${i} fi if [[ -d $1/${i} ]];then #这里的文件要给绝对路径 __count__ $1/${i} fi done return 0 } __count__ $1 echo ${cnt}
while 循环
#!/bin/bash #format while [[ condition ]]; do #statements done
#EXAMPLE read num i=1 while [[ $i != $num ]]; do echo $i i=$[$i + 1] # $[] 用来计算整数表达式的值,只能整数计算, 例如$[${1} % 2]; done
until 循环:
#!/bin/bash #format until [[ condition ]]; do #statements done
#EXAMPLE: read num i=1 until [[ $i -eq $num ]]; do echo $i let i++ done
跳出 / 继续 控制 break/continue;
#!/bin/bash read num i=0 while [[ ${i} -lt ${num} ]]; do if [[ $[ ${num} % 2 ] != 0 ]]; then let num-- continue fi if [[ ${num} -eq 4 ]]; then break fi echo ${num} #let num-- num=$[ ${num} - 1 ] done
7. 数组
三种声明的方式:
declare -a a name[subscript]=value name=(v1, v2, v3 ...) 输出数组内容 ${array[*]} ${array[@]} 数组元素个数 ${#array[@]} 数组下标 ${!array[@]} #zsh 似乎不识别@ ${!array[*]} 数组追加 array+=(a b c) 数组排序 sort 删除数组 与 元素 unset
注意点:1). zsh/bash中打印所有元素方式不同;
2). bash 中下标从0 开始,zsh 下标从1 开始