shell 基础语法
Posted 水月情缘雪飞飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell 基础语法相关的知识,希望对你有一定的参考价值。
shell 基础语法 =============================================== 推荐:http://c.biancheng.net/cpp/shell/ =============================================== 第一个Shell脚本 =============================================== 格式: (1)扩展名为sh(sh代表shell) 例如:bash.sh (2)文件头(文件头固定格式) 如:#!/bin/bash 作为可执行程序: (1)使脚本具有执行权限 ~]# chmod +x ./test.sh (2)执行脚本 1:可以不加执行权限 ~]$ bash abc.sh (直接指明文件) ~]$ bash ./abc.sh (相对路径) ~]$ bash /home/mdx/abc.sh (绝对路径) 2:必须加执行权限 (必须是绝对路径或者相对路径) ~]# ./test.sh (相对路径) ~]$ /home/mdx/test.sh (绝对路径) 解释器参数(read): 使用 read 命令从 stdin 获取输入并赋值给 PERSON 变量,最后在 stdout 上输出: read [option] ... A B -p 'PROMPT' 提示符 ~] read -p "提示符:" (接受其传入的参数) -t TIMEOUT =============================================== Shell变量 =============================================== 定义: (1)只能使用字母、数字和下划线;而且不能以数字开头。 (2)不能使用标点符号。 (3)不能使用bash里的关键字(可用help命令查看保留关键字)。 变量赋值: (1)NAME=VALUE =:赋值符号,两边不能有空格。把VALUE存储到NAME指向的内存空间中 (2)declare 命令 declare [-aAfFgilrtux] [-p] [name[=value] ...] +:指定变量的属性 -:取消变量所设的属性 -a:一个使名称索引的数组(如果支持的话) -A:一个使名称关联数组(如果支持) -i:“整数”属性 -l: to convert NAMEs to lower case on assignment -r:名字只读 -t to make NAMEs have the `trace' attribute -u:to convert NAMEs to upper case on assignment -x to make NAMEs export 重新赋值变量: (1)NAME=VALUE(再次重新赋值) 变量引用: (1)${NAME} (2)$NAME 只读变量: (1)readonly NAME(变量赋值后定义) 删除变量: (1)unset NAME 变量类型: (1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。 (2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。 (3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行 =============================================== Shell特殊变量 =============================================== (1)$0:当前脚本的文件名 ~]# vi test.sh echo $0 ~]# ./test.sh ./test.sh (2)$n:传递给脚本或函数的参数。n 是一个数字,表示第几个参数。 ~]# ./test.sh param1 param2 param3 ...... ~]# vi test.sh echo $1 (param1:第1个参数) echo $2 (param2:第2个参数) echo $3 (param3:第3个参数) ...... (3)$#:传递给脚本或函数的参数个数。 ~]# vi test.sh echo $# ~]# ./test.sh param1 param2 param3 ...... 3 (4)$*:传递给脚本或函数的所有参数。横向显示。 ~]# vi test.sh for var in "$*" do echo "$var" done ~]# ./test.sh param1 param2 param3 ...... param1 param2 param3 .... (5)[email protected]:传递给脚本或函数的所有参数。竖向显示。 ~]# vi test.sh for var in "[email protected]" do echo "$var" done ~]# ./test.sh param1 param2 param3 ...... param1 param2 param3 ... (6)$?:上个命令的执行状态,或函数的返回值。 成功:0 失败:1-255 (7)$$:当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 ~]# vi test.sh echo $$ ~]# ./test.sh 14781 =============================================== Shell替换 =============================================== 转义字符: (1)\\ 反斜杠 (2) \a 警报,响铃 (3) \b 退格(删除键) (4) \f 换页(FF),将当前位置移到下页开头 (5) \n 换行 (6) \r 回车 (7) \t 水平制表符(tab键) (8) \v 垂直制表符 命令替换: (1):`command` 反引号 (2):$(command) 变量替换: (1)${var} 变量本来的值 (2)${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。 (3)${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。 (4)${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行。 (5)${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。 =============================================== Shell运算符 =============================================== 条件测试: (1) test EXPRESSION (2)[ EXPRESSION ] (3)[[ EXPRESSION ]] 算术运算符 (1)+:加法 (2)-:减法 (3)*:乘法 (4)/:除法 (5)%:取余 (6)=:赋值 (7)==:相等 (8)!=:不相等 计算方式: (1)expr expr $a + $b $(expr $a + $b) `expr $a + $b` (注意:这是反引号) 注意:符号号两边有空格 (2)$[$a+$b] (3)let let "c = $a + $b" 或者 let "c=$a+$b" (注意:这是双引号) let c=$a+$b ( 注意:符号号两边没有空格) (4)$((expression)) c=$(( $a + $b )) 备注:空格可有可无 数字运算符: (1)-eq 是否等于 (2)-ne 是否不等于 (3)-gt 是否大于 (4)-lt 小于 (5)-ge 大于等于 (6)-le 是否小于等于 布尔运算符: (1)-not 非运算。 (2)-o 或运算。 (3)-a 与运算。 (4)! 非运算。 (5)&& 与运算。 (6)|| 或运算。 字符串运算符: (1)= 相等。 (2)!= 不相等。 (3)-z 判断字符串是否为空 (4)-n 判断字符串是否不为空 (5)str: 检测字符串是否为空。 文件测试运算符: -b file: 检测文件是否是块设备文件, -c file: 检测文件是否是字符设备文件, -d file: 检测文件是否是目录, -f file: 检测文件是否是普通文件(既不是目录,也不是设备文件), -g file: 检测文件是否设置了 SGID 位, -k file: 检测文件是否设置了粘着位(Sticky Bit), -p file: 检测文件是否是具名管道, -u file: 检测文件是否设置了 SUID 位, -r file: 检测文件是否可读, -w file: 检测文件是否可写, -x file: 检测文件是否可执行, -s file: 检测文件是否为空(文件大小是否大于0),不为空返回 true。 -a file: 检测文件(包括目录)是否存在,(-a 等同于 -e) -e file: 检测文件(包括目录)是否存在, -N file 文件自从上一次读操作之后,是否被改过 -O file 当前用户是否为文件的属主 -G file 当前用户是否为文件的属组 双目测试 FILE1 -ef FILE2 是否指向同一个文件系统的相同inode的硬链接 FILE1 -nt FILE2 FILE1文件,是否新于FILE2 FILE1 -ot FILE2 FILE1文件,是否旧于FILE2 其他运算符: ?: 三元运算符 =~ 左侧字符串是否能够被右侧的PATTERN所匹配 (说人话 包含) --------------------------------------------------------------------------------------- let 与 expr 语法详解 --------------------------------------------------------------------------------------- let:评估算术表达式 id++, id-- variable post-increment, post-decrement ++id, --id variable pre-increment, pre-decrement -, + unary minus, plus !, ~ logical and bitwise negation ** exponentiation *, /, % multiplication, division, remainder +, - addition, subtraction <<, >> left and right bitwise shifts <=, >=, <, > comparison ==, != equality, inequality & bitwise AND ^ bitwise XOR | bitwise OR && logical AND || logical OR expr ? expr : expr conditional operator =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= assignment --------------------------------------------------------------------------------------- expr:评价表达式 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0 ARG1 < ARG2 ARG1 is less than ARG2 ARG1 <= ARG2 ARG1 is less than or equal to ARG2 ARG1 = ARG2 ARG1 is equal to ARG2 ARG1 != ARG2 ARG1 is unequal to ARG2 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2 ARG1 > ARG2 ARG1 is greater than ARG2 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2 ARG1 * ARG2 arithmetic product of ARG1 and ARG2 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2 ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2 STRING : REGEXP anchored pattern match of REGEXP in STRING match STRING REGEXP same as STRING : REGEXP substr STRING POS LENGTH substring of STRING, POS counted from 1 index STRING CHARS index in STRING where any CHARS is found, or 0 length STRING length of STRING + TOKEN interpret TOKEN as a string, even if it is a keyword like 'match' or an operator like '/' ( EXPRESSION ) value of EXPRESSION --------------------------------------------------------------------------------------- =============================================== Shell注释 =============================================== 以“#”开头的行就是注释,会被解释器忽略。 =============================================== Shell字符串 =============================================== 单引号:str='this is a string' 注意: 单引号里的任何字符都会原样输出。 双引号:your_name="qinj" 注意: 双引号里变量正常输出 --------------------------------------------------------------------------------------- 字符串切片:${var:offset:number} 示例: 1:取字符串的子串 ~]# vi bash.sh var='abcdefg' echo ${var:3} ~]# ./bash.sh ~]# defg 2:${var: -length}:取字符的最右侧的几个字符。 ~]# vi bash.sh var='abcdefg' echo ${var: -3} #注意:冒号后必须有一个空白字符 ~]# ./bash.sh ~]# efg 3:从左向右截取某字符后几位 ~]# vi bash.sh var='abcdefg' echo ${var:2:2} ~]# ./bash.sh ~]# cd 4:从右向左截取某字符后几位 ~]# vi bash.sh var='abcdefg' echo ${var: -4:2} ~]# ./bash.sh ~]# de --------------------------------------------------------------------------------------- 基于模式取子串: 1:${var#*word}:删除字符串开头至此分隔符之间的所有字符。 示例: ~]# vi bash.sh var='abc/de/fg' echo ${var#*/} ~]# ./bash.sh de/fg 2:${var##*word}:删除字符串开头至此分隔符之间的所有字符; 示例: ~]# vi bash.sh var='abc/de/fg' echo ${var##*/} ~]# ./bash.sh fg 3:${var%word*}:删除此分隔符至字符串尾部之间的所有字符; 示例: ~]# vi bash.sh var='abc/de/fg' echo ${var%/*} ~]# ./bash.sh abc/de 4:${var%%word*}:删除此分隔符至字符串尾部之间的所有字符; 示例: ~]# cat bash.sh var='abc/de/fg' echo ${var%%/*} ~]# ./bash.sh abc --------------------------------------------------------------------------------------- 查找替换:(PATTERN中使用glob风格和通配符) 1:${var/PATTERN/SUBSTI}:查找var所表示的字符串中,第一次被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串; 示例: ~]# vi ./bash.sh var='aaabbbcccaaabbbccc' echo ${var/bbb/字符串} ~]# ./bash.sh aaa字符串cccaaabbbccc :2:${var//PATTERN/SUBSTI}:查找var所表示的字符串中,所有被PATTERN所匹配到的字符串,并将其全部替换为SUBSTI所表示的字符串; 示例: ~]# vi bash.sh var='aaabbbcccaaabbbccc' echo ${var//bbb/字符串} ~]# ./bash.sh aaa字符串cccaaa字符串ccc 3:${var/#PATTERN/SUBSTI}:查找var所表示的字符串中,行首被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串; 示例: ~]# vi bash.sh var='aaabbbcccaaabbbccc' echo ${var/#aa/字符串} ~]# ./bash.sh 字符串abbbcccaaabbbccc 4:${var/%PATTERN/SUBSTI}:查找var所表示的字符串中,行尾被PATTERN所匹配到的字符串,将其替换为SUBSTI所表示的字符串; 示例: ~]# vi bash.sh var='aaabbbcccaaabbbccc' echo ${var/%cc/字符串} ~]# ./bash.sh aaabbbcccaaabbbc字符串 --------------------------------------------------------------------------------------- 查找删除: 1:${var/PATTERN}:删除第一次的匹配; 示例: ~]# vi bash.sh var='aaabbbcccaaabbbccc' echo ${var/cc/字符串} ~]# ./bash.sh aaabbb字符串caaabbbccc 2:${var//PATERN}:删除最后一次匹配 示例: ~]# vi bash.sh var='aaabbbcccaaabbbccc' echo ${var//cc/字符串} ~]# ./bash.sh aaabbb字符串caaabbb字符串c 3:${var/#PATTERN}:删除行首匹配 示例: ~]# cat bash.sh var='aaabbbcccaaabbbccc' echo ${var/#aa/字符串} ~]# ./bash.sh 字符串abbbcccaaabbbccc 4:${var/%PATTERN}:删除行尾匹配 示例: ~]# cat bash.sh var='aaabbbcccaaabbbccc' echo ${var/%cc/字符串} ~]# ./bash.sh aaabbbcccaaabbbc字符串 --------------------------------------------------------------------------------------- 字符大小写转换: 1:${var^^}:所有字符转换为大写; 示例: ~]# cat bash.sh var='aaabbbcccAAABBBCCC' echo ${var^^} ~]# ./bash.sh AAABBBCCCAAABBBCCC :2:${var,,}:所有字符转换为小写; 示例: ~]# cat bash.sh var='aaabbbcccAAABBBCCC' echo ${var,,} ~]# ./bash.sh aaabbbcccaaabbbccc --------------------------------------------------------------------------------------- 变量赋值: 1:${var:-VALUE}:如果var变量为空,或未设置,那么返回VALUE;否则,则返回var变量的值; 示例: ~]# cat bash.sh var='字符串' echo ${var:-string} echo ${ar:-string} ~]# ./bash.sh 字符串 string 2:${var:=VALUE}:如果var变量为空,或未设置,那么返回VALUE,并将VALUE赋值给var变量;否则,则返回var变量的值; 示例: ~]# cat bash.sh var='字符串' echo ${var:=string} echo ${ar:=string} echo $ar ~]# ./bash.sh 字符串 string string 3:${var:+VALUE}:如果var变量不为空,则返回VALUE; 示例: ~]# cat bash.sh var='字符串' echo ${var:+string} ~]# ./bash.sh string 4:${var:?ERROR_INFO}:如果var为空,或未设置,那么返回ERROR_INFO为错误提示;否则,返回var值; 示例: ~]# cat bash.sh var='字符串' echo ${var:?string} echo ${ar:?错误信息} ~]# ./bash.sh 字符串 ./bash.sh: line 4: ar: 错误信息 --------------------------------------------------------------------------------------- 拼接字符串 示例: ~]# vi bash.sh your_name="qinjx" greeting="hello, "$your_name" !" greeting_1="hello, ${your_name} !" echo $greeting $greeting_1 ~]# ./bash.sh hello, qinjx ! hello, qinjx ! --------------------------------------------------------------------------------------- 获取字符串长度:${#string} 示例: ~]# vi bash.sh string='abcd' echo ${#string} echo $(expr length $string) ~]# ./bash.sh 4 4 =============================================== Shell if else语句 =============================================== (1)单分支1 if CONDITION ; then 分支 fi (2)单分支2 if CONDITION ; then 分支1 else 分支2 fi (3)多分支1 if CONDITION1; then 分支1 elif CONDITION2; then 分支2 ... elif CONDITION; then 分支n fi (4)多分支2 if CONDITION1; then 分支1 elif CONDITION2; then 分支2 ... else CONDITION; then 分支n fi 语法:then可换行写,condition后面就不用加分号。 if CONDITION then 分支 fi =============================================== Shell case esac语句 =============================================== (1)语法结构 case $VARAIBLE in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 分支n ;; esac 示例: value='c' case $value in a) echo '这是a' # 可以是单引号或者双引号 ;; b) if [0 -le 18];then # 可以是一段代码 echo '一个判断' fi ;; c) echo 这是c ;; # 必须以;;为结束 *) echo "未匹配到上面的结果,在此可以执行一段代码或者不写 *) 这一部分" ;; esac 结果: 这是c =============================================== Shell for循环 =============================================== (1)语法结构 for 变量 in 列表; do command done 示例: 1:详细输出,依次输出1,2,3,4,5 for File in 1 2 3 4 5 do echo $File done 2:输出某个目录下所有的文件或者匹配到的文件 for file in $HOME/.bash*; do # 也可以写 $HOME/* echo $file done 3:{开始正整数..结束正整数}:注意:中间是两个点 for num in {1..5}; do echo $num # 输出数字 1-5 的正整数 done 4:((i=1; i<=5; i++ )):每次循环加1 for((i=1; i<=5; i++ )); do echo $i # 输出数字 1-5 的正整数 done 5:执行命令 seq:起始从1开始 for i in $(seq 5); do echo $i # 输出数字 1-5 的正整数 done 6:执行命令 for i in $(ls /); do echo $i done 语法:do可以换行写,那里就不需要分号了。 =============================================== Shell while循环 =============================================== (1)语法结构 while CONDITION; do 代码.... done 注意: 进入条件: CONDITION 测试为”真“ 退出条件: CONDITION 测试为”假“ 示例: (1) declare -i i=1 while [ $i -le 5 ]; do echo $i let i++ done 或者 declare -i i=1 while (( $i <= 5 )); do echo $i let i++ done =============================================== Shell until循环 =============================================== (1)语法结构 until CONDITION; do 循环体 循环控制变量修正表达式 done 注意: 进入条件:CONDITION测试为”假“ 退出条件:CONDITION测试为”真“ 示例: declare -i i=1 until (( $i > 5 )); do echo $i let i++ done 或者 declare -i i=1 until [ $i -gt 5 ]; do echo $i let i++ done =============================================== Shell跳出循环 =============================================== (1)continue:跳过本次循环,执行下一次循环 (2)break:退出循环 =============================================== Shell函数 =============================================== (1)语法一: function f_name { ...函数体... } (2)语法二: f_name() { ...函数体... } 执行函数: f_name 示例: 1: #函数的声明 function fname { echo '我是语法一函数' } # 执行函数 fname 2: # 函数的声明 fname(){ echo '我是语法二函数' } # 执行函数 fname 参数: (1)$1,$2, ... (2)$# [email protected] $* 示例: function fname { echo "第一个参数:$1" echo "第二个参数:$2" # echo "第N个参数:$n" echo "参数总数:$#" echo "参数字符串: [email protected]" echo "参数字符串: $*" } #执行函数,并传入参数 fname 1 2 结果: 第一个参数:1 第二个参数:2 参数总数:2 参数字符串: 1 2 参数字符串: 1 2 return:返回退出状态码,shell不退出 示例: function fname { return 1 } fname echo $? 结果: 1 exit:返回状态码并推出 作用域: (1)全局作用域:没有使用 local 关键字;语法:VARIABLE=VALUE (2)局部作用域:函数内部声明并且使用 local 关键字,仅在函数内部有效:语法:local VARIABLE=VALUE 示例: name=tom # 全局作用域 setname() { local name=jerry # 局部作用域,仅在函数内部有效。 echo "局部: $name" } setname #执行函数 echo "全局: $name" =============================================== Shell数组 =============================================== 声明数组: declare -a NAME:声明索引数组; declare -A NAME:声明关联数组; 数组中元素的赋值方式: (1) 一次只赋值一个元素; ARRAY_NAME[INDEX]=value 示例:索引数组 declare -a index_array; index_array[0]=0 index_array[1]=1 echo ${index_array[0]} 示例:关联数组 declare -A array_name array_name[aa]=aaaa array_name[bb]=bbbb echo ${array_name[aa]} (2) 一次赋值全部元素; ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...) 示例:索引数组 declare -a index_array; index_array=('val0' 'val1' 'val2') echo ${index_array[0]} (3) 只赋值特定元素; ARRAY_NAME=([0]="VAL1" [3]="VAL4" ...) 示例:索引数组 declare -a index_array; index_array=([0]='val0' [3]='val1' [6]='val2') echo ${index_array[6]} 示例:关联数组 declare -A array_name array_name=([aa]='aaaa' [bb]='bbbb') echo ${array_name[aa]} 注意:bash支持稀疏格式的数组; (4) read -a ARRAY_NAME 示例: read -p "输入参数: " -a array_name echo ${array_name[0]} (5) 引用数组中的元素:${ARRAY_NAME[INDEX]} 注意:引用时,只给数组名,表示引用下标为0的元素; (6)数组的长度(数组中元素的个数): ${#ARRAY_NAME[*]} ${#ARRAY_NAME[@]} 示例: declare -a array_name array_name[0]=00000 array_name[1]=1111 array_name[2]=2222 echo ${#array_name[@]} echo ${#array_name[*]} 结果: 3 3 (7)数组的参数(数组中所有的参数): ${ARRAY_NAME[*]} ${ARRAY_NAME[@]} 示例: declare -a array_name array_name[0]=00000 array_name[1]=1111 array_name[2]=2222 echo ${array_name[@]} echo ${array_name[*]} 结果: 00000 1111 2222 00000 1111 2222 =============================================== Shell输入输出重定向 =============================================== 推荐:http://www.cnblogs.com/chengmo/archive/2010/10/20/1855805.html linux shell下常用输入输出操作符是: 1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ; /dev/stdin -> /proc/self/fd/0 0代表:/dev/stdin 2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ; /dev/stdout -> /proc/self/fd/1 1代表:/dev/stdout 3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ; /dev/stderr -> /proc/self/fd/2 2代表:/dev/stderr 输出重定向: 1:重定向程序正常执行的结果 覆盖重定向:覆盖目标文件中的原有内容; COMMAND > /PATH/TO/SOMEFILE 追加重定向:追加新产生的内容至目标文件尾部; COMMAND >> /PATH/TO/SOMEFILE shell的一个功能开关: # set -C 禁止覆盖输出重定向至已存在的文件; 注意:此时仍然可以使用“>|”至目标文件; # set +C 关闭上述特性; 错误重定向: 重定向错误的执行结果; COMMAND 2> /PATH/TO/SOMEFILE 错误输出覆盖重定向; COMMAND 2>> /PATH/TO/SOMEFILE 错误输出追加重定向; 合并标准输出与错误输出流: (1) &>, &>> (2) COMMAND > /PATH/TO/SOMEFILE 2>&1 COMMAND >> /PATH/TO/SOMEFILE 2>&1 特殊输出目标:/dev/null 位桶:bit bucket 特殊的输入文件:/dev/zero 输入重定向: COMMAND < /PATH/FROM/SOMEFILE COMMAND << : Here Document 用法: COMMAND << EOF COMMAND > /PATH/TO/SOMEFILE << EOF =============================================== Shell文件包含 . 与 source =============================================== 文件包含:. (点) 与 source 都可以引入文件 注意: 1:被引入的文件不需要执行权限 2:可以没有 #!/bin/bash 3:被引入程序当做一个可执行的脚本运行。 示例: ~]# vi bash.sh #!/bin/bash # 引入 config.sh 文件 . ./config.sh # 引入 cfg 文件 source ./cfg echo $string echo $cfg ~]# vi cfg cfg='cfg文件' ~]# vi config.sh #!/bin/bash string='config文件' ~]# ./bash.sh config文件 cfg文件
以上是关于shell 基础语法的主要内容,如果未能解决你的问题,请参考以下文章