首页 > 代码库 > shell 基础语法
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里的keyword(可用help命令查看保留keyword)。 变量赋值: (1)NAME=VALUE =http://www.mamicode.com/:赋值符号。两边不能有空格。
把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)$@:传递给脚本或函数的全部參数。
竖向显示。 ~]# vi test.sh for var in "$@" 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=http://www.mamicode.com/'c'>
=============================================== 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)$# $@ $* 演示样例: function fname { echo "第一个參数:$1" echo "第二个參数:$2" # echo "第N个參数:$n" echo "參数总数:$#" echo "參数字符串: $@" echo "參数字符串: $*" } #运行函数,并传入參数 fname 1 2 结果: 第一个參数:1 第二个參数:2 參数总数:2 參数字符串: 1 2 參数字符串: 1 2 return:返回退出状态码。shell不退出 演示样例: function fname { return 1 } fname echo $? 结果: 1 exit:返回状态码并推出 作用域: (1)全局作用域:没有使用 local keyword;语法:VARIABLE=VALUE (2)局部作用域:函数内部声明并且使用 local keyword,仅在函数内部有效:语法: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 基础语法