Shell 是指一种运用程序,这个运用程序供应了一个界面,用户通过这个界面访问操作系统内核的做事。
Ken Thompson的sh是第一种UnixShell,Windows Explorer是一个范例的图形界面Shell。
shell脚本shell script,是一种为shell而编写的脚本程序。
然而常日所说的shell却是指shell脚本,而非shell本身。

Linux系统shell种类浩瀚,常用的有sh和bash。
shell脚本用#!/bin/bash或#!/bin/sh之类的办法,制订运行脚本的shell,#!是识别符号。
#!/bin/shecho "Hello World"
运行shell脚本的两种方法:
作为可实行程序
将shell文本保存为.sh格式文件,授予实行权限
chmod + x ./test.sh # 授予可实行权限./test.sh #实行脚本,把稳此处须要指明当前目录下的test.sh哦,不然会去path路径找的,呵呵。
作为阐明其参数
直接阐明运行,如此就不用写#!/bin/sh之类的引用注释了。
/bin/sh test.sh# 类似java、php、python脚本 /bin/php test.php
Shell变量
变量命名语法,不须要$符号,php须要。
命名哀求:
首字母必须字母a-z或A-Z
不能空格,可用_
不能标点
不能利用bash关键字
把稳,不同于其他编程措辞,等号之间不要有空格。
your_variable="your,name"# 利用语句给变量赋值,如下循环显示出/etc目录下的文件名for file in 'ls /etc'
利用变量
利用已定义变量,只需在变量前加$符号即可:
your_variable='yourname'echo $your_variableecho $(your_variable)
变量名可以加{}来标识变量名的范围,如:
for skill in Ada Coffe Action Java; do echo"I am good at ${skill}Script"done
如果不加{},skill就可能被认为skillScript而导致变量找不到
已定义的变量可重新定义:
your_name="tom"echo $your_nameyour_name="john"echo $your_name
只读变量
利用readonly命令将变量只读,则不可再改变,否则报错。
#!/bin/bashmyUrl="test"readonly myUrlmyUrl="new url" #此处就会报错,由于变量只读了。
删除变量
利用unset命令删除变量:
unset variable_name
删除变量后不能再用,而unset不能删除只读变量
#!/bin/shmyUrl="http://www.google.com"unset myUrlecho $myUrl #此时输出就没结果了,由于变量被删除了。
变量类型
运行shell时,会同时存在三种变量:
局部变量:脚本中定义的变量,仅浸染于本shell脚本内。
环境变量:所有程序,包括shell启动程序都能访问的环境变量。
shell变量:shell程序的分外变量。
shell常用number和string,个中string可以单引号、双引号或者不用引号。
但是略有差异:
单引号
str='string test'
单引号''之间的字符原样输出,里面的变量也会失落效。
其内部不能再有单引号,哪怕转义符号都失落效。
双引号
your_name='your name'str="Hello ,world ,\"$your_name\"!\n"
双引号里面可以有变量,可以有转义符号。
字符串拼接
n1="abc"test="hello, "$n1" !"test1="hello, ${n1} !"echo $test $test1
获取字符串长度
利用#标识变量长度
str="abcdef"#输出字符串长度echo ${#str}
Shell数组
bash仅支持一维数组,可利用下标或表达式操作元素。
定义数组
shell中利用()表示数组,元素用空格来分割。
array=(1 2 3 4 5 6 7)#或者array=(abc)#也可以单独定义,下标可以不连续,也无范围限定。
array[0]=1array[1]=2array[3]=7
读取数组
variable=${array[index]}# @符号代替index表示获取所有元素echo ${variable[@]}
获取数组长度
类似字符串的获取
#获取元素个数length=${#array_name[@]}#或者通配符length=${#array_name[]}#获取数组单个元素的长度length_n=${#array_name[n]}
Shell注释
利用#至于行首,表示该行注释,shell无多行注释,只能每行都#
#-----------------------#我是个多行注释#但是只能这么写#-----------------------
假如多行代码须要注释,可以将定义为函数,加{}包裹起来,该函数不被调用,则类似于注释掉。
在实行shell脚本时,可以向脚本通报参数
#!/bin/bash#传参测试echo "Shell 传参测试";echo "file name: $0";echo "first variable: $1";echo "second variable: $2"echo "third variable: $3";
通过授予权限,或者指定实行,可实现输出:
$ chmod +x test.sh# $符号在次表示root用户实行,下面是传入1,2,3,三个数到脚本$ ./test.sh 1 2 3
#输出结果:Shell 传参测试file name: ./test.shfirst variable: 1second variable 2third variable 3
参数处理
解释
$#
通报到脚本的参数的个数
$
以一个单字符串显示所有向脚本通报的参数。
$$
脚本运行确当提高程ID号
$!
后台运行的末了一个进程的ID号
$@
类似$,利用时许加引号,并在引号中返回每个参数。
$
显示shell利用确当前选选项,类似set命令
$?
显示末了命令的退出状态。
0 表示无缺点。
其他都是错。
#!/bin/shecho "Shell 通报参数实例!
";echo "第一个参数为:$1";echo "参数个数为:$#";echo "通报的参数作为一个字符串显示:$";
$ chmod +x test.sh$ ./test.sh 1 2 3Shell 通报参数实例!
第一个参数为:1参数个数为:3通报的参数作为一个字符串显示:1 2 3
∗与∗与@的异同:都是运用所有参数不同:只有在双引号中表示。
假设在脚本运行时写了三个参数 1、2、3,,则” ”等价于 “1 2 3”(通报了一个参数),而 “@” 等价于 “1” “2” “3”(通报了三个参数)。
#!/bin/bashecho "-- \$ demo ---"for i in "$";doecho $idoneecho "-- \$@ demo ---"for i in "$@"; doecho $idone
实行效果:
$ chmod +x test.sh$ ./test.sh 1 2 3-- $ 演示 ---1 2 3-- $@ 演示 ---
Shell数组
Bash shell仅支持一维数组,不限定大小,初始化时候不须要指定大小。
下标0开始,()包裹,空格分割元素。
array=(a b c d)读取数组
格式${array[index]}
#!/bin/bashmy_array=(a b "c" d)echo "first: ${my_array[0]}"#然后实行文件,得到输出结果#可用@或来代替index获取所有元素
数组长度
类似字符串的长度获取
${#array[index]}
Shell运算符
shell支持多种运算符:算数运算符关系运算符布尔运算符字符串运算符文件测试运算符原生Bash不支持大略的数学运算,可以用awk和expr实现。
#!/bin/shval=`expr 2 + 2`echo $val#把稳,expr用反引号,表达式和运算符之间必须有空格,2+2就弗成。
算术运算符若a = 10,b = 20
#!/bin/basha=10b=20val=`expr $a + $b`echo "a + b : $val"val=`expr $a - $b`echo "a - b : $val"val=`expr $a \ $b`echo "a b : $val"val=`expr $b / $a`echo "b / a : $val"val=`expr $b % $a`echo "b % a : $val"if [ $a == $b ]then echo"a 即是 b"fiif [ $a != $b ]then echo"a 不即是 b"fi
实行结果:
a + b : 30a - b : -10a b : 200b / a : 2b % a : 0a 不即是 b
乘号须要在expr表达式内用\转义
关系运算符布尔类型,关系运算符仅支持数字,除非字符串的值也是数字。
示例,若a = 10 ,b = 20:
布尔运算符
逻辑运算符字符串运算符文件测试运算符Shell echo命令类似于php的echo,shell的echo用于输出字符串,格式echo string显示普通字符串
echo "Hello World"#可以不带引号 echo Hello World
显示转义字符
echo "\"It is a test\""#输出结果"It is a test"
显示变量read命令从标准输入中读取一行,并把输入行的每个字段指定给shell变量
#!/bin/shread nameecho "$name It is a test"#运行效果:[root@www ~]# sh test.shOK #标准输入OK It is a test #输出
显示换行
echo -e "Ok ! \n" # -e 开启转义echo "It is a test"#输出结果:把稳ok后面有换行OK!It it a tes
显示不换行
#!/bin/shecho -e "OK! \c" # -e 开启转义 \c 不换行echo "It is a test"#结果:OK! It is a test
显示结果定向至文件
echo "It is a test" > test.txt
原样输出字符,不转义不取变量,须要结合单引号
echo '$name\"'
Shell text命令
shell中test命令用于测试条件是否成立,可进行数字、字符和文件的条件测试
#!/bin/bash#用之前的各种运算符,测试testnum1=100num2=200if test $[num1] -eq $[num2]then echo'true'else echo'false'fi
Shell 流程掌握
差异于其他编程措辞,shell的流程掌握不可为空,如
if(a>b){ System.out.println("ok");}else{ //此处不做任何事}
但是在shell中不能涌现不做任何事的分支语句
if elseif语句格式
if conditionthencommand1command2...fi # 是if的倒写
每个句子可以用;分号结束,可以写在一行好几个语句。
if else
if conditionthencommand1command2...elsecommandfi
if else-if else
if condition1thencommand1elif condition2 #类似python中,else if是写作elifthencommand2elsecommandfi
for循环shell的for循环格式:
for var in item1 item2 ... itemNdo command1 command2 ...done #for循环结束的标识#写成一行for var in item1 item2 ... itemN;docommand1; command2;...;done;
while语句格式:
while conditiondo commanddone
示例:
#!/bin/shint=1while(( $int<=5 ))do echo $int let "int++" # let是个关键命令done
可以结合read命令吸收输入信息无限循环
while :do commanddone#或者while truedo commanddone#或者for (( ; ; ))
until循环shell所有的until循环类似于一个分外的for循环,知道知足条件时候才停滞。
一样平常还是
whileuntil conditiondo commanddone
条件可为任意测试条件,测试发生在循环末端,因此循环至少实行一次—请把稳这一点。
跳出循环shell也利用break和continue来跳出循环。
break
跳出所有循环,终止后面的实行。
#!/bin/bashwhile :do echo-n "输入 1 到 5 之间的数字:" readaNum case$aNum in 1|2|3|4|5) echo "你输入的数字为$aNum!" ;; ) echo "你输入的数字不是 1 到 5 之间的! 游戏结束" break ;; esacdone
continue
跳出本次循环,实行下一轮循环
#!/bin/bashwhile :do echo-n "输入 1 到 5 之间的数字: " readaNum case$aNum in 1|2|3|4|5) echo "你输入的数字为$aNum!" ;; ) echo "你输入的数字不是 1 到 5 之间的!" continue echo "游戏结束" ;; esacdone
esaccase语句差异于C措辞,用esac作为结束标志,)和;;标识每个case。
shell可以自定义函数,然后自己调用。
函数格式:
#function 关键字为可选项,参数也是可选[ function ] funname [()]{ action; [returnint;]}
解释:可以带function fun()定义,也可以fun()定义,不带参数。
参数返回,可以显示加: return 返回,若不加,则返回末了一条指令结果。
#!/bin/bashdemoFun(){ echo"这是我的第一个 shell 函数!"}echo "-----函数开始实行-----"demoFunecho "-----函数实行完毕-----"
含有返回值的函数:
#!/bin/bashfunWithReturn(){ echo"这个函数会对输入的两个数字进行相加运算..." echo"输入第一个数字: " readaNum echo"输入第二个数字: " readanotherNum echo"两个数字分别为$aNum 和$anotherNum !" return$(($aNum+$anotherNum))}funWithReturnecho "输入的两个数字之和为 $? !"
函数参数
在Shell中,调用函数时可以向其通报参数。
在函数体内部,通过 n的形式来获取参数的值,例如,1表示第一个参数,$2表示第二个参数…
#!/bin/bashfunWithParam(){ echo"第一个参数为$1 !" echo"第二个参数为$2 !" echo"第十个参数为$10 !" echo"第十个参数为${10} !" echo"第十一个参数为${11} !" echo"参数总数有$# 个!" echo"作为一个字符串输出所有参数 $ !"}funWithParam 1 2 3 4 5 6 7 8 9 34 73#输出结果:第一个参数为1 !第二个参数为2 !第十个参数为10 !第十个参数为34 !第十一个参数为73 !参数总数有11 个!作为一个字符串输出所有参数1 2 3 4 5 6 7 8 9 34 73 !
把稳:$10不能获取第10个参数,由于当n>=10时候,要用$(n)来获取参数。
类Uinx系统中,默认标准输入输出设备便是shell终端。
重定向命令列表:
把稳:须要把稳的是文件描述符 0 常日是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准缺点输出(STDERR)。
输出重定向
command1 > file1
若file1存在,则被替代。
可以用>>追加符号,则不替代。
输入重定向
command1 < file1command1 < infile > outfile
同时更换输入和输出,实行command1,从文件infile读取内容,然后将输出写入到outfile中。
重定向深入讲解一样平常类unix系统命令运行会同时打开三个文件:标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
标准缺点文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入缺点信息默认情形下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
#仿照终端$ command 2 > file
若要追加>>符号,个中2代表标准缺点文件的代号。
如果希望将stdout和stderr合并后重定向到file
command > file 2>&1#或者command >> file 2>&1#如果输入、输出都重定向command <file1 >file2
Here DocumentHere Document是shell的一种分外重定向办法,用于将输入重定向到一个交互式shell脚本或程序:
command << delimiter documentdelimiter
浸染将delimiter之间的document作为输入通报给command
把稳:结尾的delimiter前后不得有任何符号,包括tab和空格。
wc -l << EOF nihao zhendehenhao shime okEOF
/dev/null文件若希望实行命令不在屏幕输出,可重定向到/dev/null
command > /dev/null
/dev/null为分外文件,写入的内容立即不见,不可读出。
如果屏蔽stdout和stderr
command > /dev/null 2>&1
Shell文件包含
shell也可以利用外部脚本,便于封装:
. filename #把稳点号(.)与文件名之间有空格
或
source filename
示例:test1.sh
#!/bin/bashurl="http://www.baidu.com"
test2.sh
#!/bin/bash#利用 . 号来引用test1.sh 文件. ./test1.sh# 或者利用以下包含文件代码# source ./test1.shecho "地址:$url"
实行时候test2.sh只须要test2.sh有实行权限即可,test1.sh不一定须要。