Bash基础

来源:互联网 发布:温州淘宝摄影培训班 编辑:程序博客网 时间:2024/06/06 03:27

1.hello world

假如我们有个名为hello.sh的文件,其内容如下

#!/bin/bashecho "Hello world!"

为其添加执行权限

chmod u+x hello.sh

运行脚本,会输出 Hello world!

./hello.sh

脚本内容的第一行是必须写的,它用来说明后续命令用/bin下的bash执行

2.基本语法

设置变量

#注意等号两边不能有空格myvalue1=hello#用$符引用变量echo $myvalue1 #hello#当变量值有空格时要加引号myvalue2="hello world!"#单双引号的区别#单引号表示字面值echo 'My value is $myvalue1' #My value is $myvalue1#双引号会对里面的内容求值echo "My value is $myvalue1" #My value is hello#变量名后有其它字符时可以用{}括起来echo "${myvalue1}world" #helloworld#删除变量unset myvalue1#注意myvalue1前没有$符#unset同样适用于数组与函数

数组

#数组成员以空格分割,当成员自身含有空格时,需要用"或'括起来myarray=(hello world! "animal dog")#访问数组成员echo ${myarray[0]} #hello#输出所有成员echo ${myarray[@]} #hello world! animal dog#得到数组成员数量echo ${#myarray[@]} #3

if语句

#注意if与[,[与-d,-d与"$myvalue","$myvalue"与]之间必须有空格#[]也可以换为test,例如 if test -d "$myvalue"#关于-d,-f的含义会在以后说明if [ -d "$myvalue" ]then    echo directoryelif [ -f "$myvalue" ]then    echo fileelse    echo "not directory and file"fi

for语句

#用for操作数组myarray=(hello world! "animal dog")#直接循环输出值for myvalue in ${myarray[@]}do    echo $myvaluedone#结果为#hello#world!#animal#dog#注意虽然我们在数组成员中加了"#但是用这种方式仍然把空格当成了分隔符#即把"animal dog"当成了两个数组成员#使用索引#注意myarray前的!for i in ${!myarray[@]}do    echo "$i : ${myarray[$i]}"done#结果为#0 : hello#1 : world!#2 : animal dog#注意这种方式与上面的区别:把"animal dog"当成了一个成员变量#用for操作字符串mystr="hello world!"for myvalue in $mystrdo    echo $myvaluedone#结果为#hello#world!

case语句

myday=Mondaycase $myday inSaturday)    echo "Play computer games"    ;;Sunday)    echo "Reading books"*)    echo "Study"    ;;esac#对于此例来说输出结果为:Study#值得注意的是除最后一个case语句(在此例中为 *) )#其它语句最后一定要加 ;;,否则会有语法错误#另外 *)表示匹配所有非其上面case语句的结果#相当于c的default语句#case语句还支持简单的正则表达式case $myday inSaturday|Sunday) #Saturday 或 Sunday    echo "Play"    ;;*)    echo "Study"esacmynum=100case $mynum in[1-9][0-9]*)    echo "It's interger"    ;;*)    echo "It's not interger"esac

while语句

#当满足条件时,循环执行while内的命令mynum=10sum=0while [ "$mynum" -gt 0 ]do    sum=`expr $sum + $mynum`    mynum=`expr $mynum - 1`doneecho $sum #55#说明:在进行数字比较时$mynum两边的"可要可不要#但进行字符串比较时一定要加",否则可能会出莫名其妙的结果#-gt表示大于#``(不是单引号,是~下的字符)表示取得命令的结果,也可以用$()#expr表示执行数学运算,shell不支持直接的数学运算#这些会在后面详细说明,在这里先了解一下

until语句

#当满足条件时,跳出until内的命令#用until实现上述while的功能mynum=10sum=0until [ "$mynum" -lt 1 ]do    sum=`expr $sum + $mynum`    mynum=`expr $mynum - 1`doneecho $sum #55#说明:-lt表示小于#当mynum的值小于1时,跳出until

break与continue

#shell也支持break与continue语句,后面不加数字时其用法与c相同#与c不同的是#在shell中我们可以用 break n和continue n 的格式跳出n层循环#continue的例子sum=0for i in 1 2 3 4 5do    if [ $i -eq 3 ]    then        continue    fi    sum=`expr $sum + $i`doneecho $sum #12#break的例子sum=0for i in 1 2 3 4 5do    if [ $i -eq 3 ]    then        continue    fi    sum=`expr $sum + $i`doneecho $sum #3

给shell传递参数

#shell用$0保存脚本名称,用$n保存参数,用$#保存参数个数#$@与$*表示所有的参数,关于它们的区别一会儿说明#对于参数1-9,用$1-$9引用即可,对于10以上的参数,用类似${10}#这样的格式引用#脚本param.sh的内容如下#!/bin/bashecho "脚本名称:$0"echo "参数个数:$#"echo "参数:$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}"#调用脚本./param.sh 1 2 3 4 5 6 7 8 9 10#输出结果为:#脚本名称:./param.sh#参数个数:10#参数:1 2 3 4 5 6 7 8 9 10#使用shift左移参数while [ -n "$1" ]do    echo -n $1    shiftdone#结果为:12345678910#说明:第一个-n表示在$1不为空时为真#第二个-n表示不换行,shift表示所有参数(除了$0)向左移位#并丢弃被移出的值,另外可以用shift n的格式指定移位个数#例如while [ -n "$1" ]do    echo -n $1    shift 2done#结果为:13579#关于$*与$@的区别#在没有双引号时,两者结果一样,有双引号时$*会把所有的参数当成一个值#而$@会将参数当成分隔的值,我们看下面的例子#假如脚本名称是test.sh,我们这样运行脚本:./test.sh a b c dfor myvalue in $*do    echo $myvaluedone#结果是:#a#b#c#dfor myvalue in $@do    echo $myvaluedone#结果是:#a#b#c#dfor myvalue in "$*"do    echo $myvaluedone#结果是:#a b c dfor myvalue in "$@"do    echo $myvaluedone#结果是:#a#b#c#d

函数

#定义函数function hello(){    echo "hello $1"}#调用函数hello world! #hello world!  #说明:function关键字可有可无,取决于你的习惯#给函数传递的参数可以在函数内部使用$1-$n的得到#其它方面如$*,$@,$#,$0,shift等的用法与给shell脚本#传递参数的用法相同

3.条件测试

基本格式

#其实在上面大家已经见过了,有两种基本格式test condition[ condition ]#这两种格式可以互用,没什么区别

文件测试

命令 说明 -d 如果是目录则为真 -f 如果是普通文件则为真 -e 如果文件或目录存在则为真 -s 如果文件非空则为真 -L 如果是符号连接则为真 -r 如果可读则为真 -w 如果可写则为真 -x 如果可执行则为真 -u 如果文件suid位设置了则为真 -O 如果文件存在并属当前用户所有则为真 -G 如果文件存在并且默认组与当前用户相同则为真 file1 -nt file2 如果file1比file2新则为真 file1 -ot file2 如果file1比file2旧则为真
#一个例子myfile="test.txt"if [ -e "$myfile" ]then    echo "exist"else    echo "not exist"fi#使用逻辑操作符myfile1="test1.txt"myfile2="test2.txt"if [ -e "$myfile1" -a -e "$myfile2" ]then    echo "both exist"else    echo "not both exist"fi#-a表示and,即逻辑与,都为真才为真#-o,逻辑与,存在一个为真就为真#!,逻辑否

字符串测试

命令 说明 = 如果两个字符串相等则为真 != 如果两个字符串不等则为真 str1 \> str2 如果str1非相等部分的第一个值的ASCII码大于str2则为真 str1 \< str2 与>相反 -z 如果字符串为空则为真 -n 如果字符串非空则为真
#>和<前必须加反斜杠,否则会被当做重定向符#一个例子str=helloif [ "$str" = hello ]then    echo "Right"else    echo "Wrong"fi#需要注意的是在进行字符串测试时最好加双引号,否则可能会出现非预期的结果#看下面的例子str=""if [ -n $str ]then    echo "not empty"else    echo "empty"fi#结果为:not empty#若给$str加上双引号,结果为empty,这才符合我们的预期结果

数值测试

命令 说明 -eq 相等则为真 -ne 不等则为真 -gt 大于则为真 -lt 小于则为真 -ge 大于等于则为真 -le 小于等于则为真
#一个例子mynum=10if [ $mynum -gt 5 ]then    echo "大于5"else    echo "不大于5"fi#需要注意的是被测试的值只能是整数,否则会报错

4.在shell中执行命令

#直接执行即可#如下面的命令表示在当前路径下创建一个文件夹mytestmkdir mytest#用$?来检查上个命令是否执行成功#$?自动保存上次命令的退出情况,0表示正常退出,1表示有错误发生echo $?#若当前路径下没有mytest,执行成功,$?的值为0#若当前路径下有mytest,执行失败,$?的值为1#用$$获得本脚本的进程号(PID)echo $$#用$!获得最后一个程序的进程号(PID)echo $!#用``或$()取得命令的执行结果for myvalue in `cat mytest.txt`do    echo $myvaluedone#或for myvalue in $(cat mytest.txt)do    echo $myvaluedone

5.引用另一脚本文件的内容

假如我们有一个名为test1.sh的脚本,其内容为

#!/bin/bashecho "I'm test1.sh"test1_func(){    echo "I'm test1.sh's function"}

在同目录下有一个名为test2.sh的脚本,其内容为

#!/bin/bashsource test1.shtest1_func

我们执行test2.sh,输出结果为

I’m test1.sh
I’m test1.sh’s function

上面的source就表示包含另一个脚本

#在test2.sh中我们也可以用.来包含,.与source没有区别#例如. test1.shtest1_func#另一个可以表示包含的命令是sh,但是sh会在子shell中执行#被包含的脚本,其中的函数我们是无法访问的#例如sh test1.shtest1_func#会报错,说 test1_func:未找到命令#所以我们最好使用source或.来包含其它脚本

6.` `,$( ),( ),(( )),$[ ],[ ],[[ ]]的用法
` `与$( )的用法

#两者都获得命令的执行结果,没什么区别mylist1=`ls -al`mylist2=$(ls -al)#两者结果是一样的

( )的用法

#圆括号中的命令会在子shell中执行,看下面的例子a=1;b=1(a=2;b=2)echo "$a,$b" #结果为: 1,1a=1;b=1a=2;b=2echo "$a,$b"#结果为: 2,2#在一行中执行多个命令用 ; 分隔即可

(( ))的用法

#(( ))支持:val++,val--,++val,--val,+,-,*,/#~按位求反,&按位与,|按位或,&&逻辑与,||逻辑或#**幂运算,<<左位移,>>右位移a=10b=5echo $(($a - $b)) #5echo $(($a * $b)) #50echo $(($a / $b)) #2echo $((a++)) #10echo $((++a)) #11#值得说明的是在expr中的乘号必须被转义,即echo `expr $a \* $b`#而在$(( ))中不需要被转义#在if中使用(( ))val=10if(($val**2 > 20))    echo "right"fi#在for中使用(( ))for((i=1,j=5;i<=5;i++,j--))do    echo "$i $j"done#结果为:#1 5#2 4#3 3#4 2#5 1

$[ ]的用法

#$[ ]与$(( ))的用法一样,都能对数学表达式求值#只是(( ))多了一些上面写的特殊用法而已a=10b=5echo $[$a - $b] #5echo $[$a * $b] #50echo $[$a / $b] #2echo $[a++] #10echo $[++a] #11

[ ]的用法

#[ ]用于条件测试,与test一样

[[ ]]的用法

#[[ ]]除了test命令中采用的标准字符串比较,还提供了一个高级特性-模式匹配#以下语句打印参数中以a开头的参数for myvalue in $@do    if [[ "$myvalue" == a* ]]    then        echo $myvalue    fidone

7.带类似-a,-f file格式的参数的shell脚本的编写
用getopts命令来格式化参数

#getopts的基本格式getopts optstring variable#将需要的选项字母列在optstring中,如果选项字母需要参数就在后面加冒号#如果要去掉错误消息的话就在optstring前加一个冒号#getopts命令将当前参数保存在命令行中定义的variable中#若当前参数不在参数列表中会将variable的值设为?#getopts会设置两个环境变量:OPTARG和OPTIND#OPTARG会保存选项后的参数值(如果有)#OPTIND保存了参数列表中getopts正在处理的参数位置#一个例子while getopts :ab:c optdo    case "$opt" in    a)        echo "found -a option"        ;;    b)        echo "found -b option with value $OPTARG"        ;;    c)        echo "found the -c option"        ;;    *)        echo "unknown option:$opt"        ;;    esacdone#说明:":ab:c"的最前面的冒号表示忽略错误信息#(默认情况下若提供的参数不在参数列表中会报错,最前面的:忽略这个错误信息)#b后的:表示-b选项后需要跟一个参数#假如脚本名称为test.sh#我们这样运行脚本:./test.sh -a -b test -c -d#结果为:#found -a option#found -b option with value test#found -c option#unknown option:?#也可以这样运行:./test.sh -acd -b test#结果和上面类似,只是顺序有所差别而已

8.获得用户输入
read的使用

#基本用法echo -n "Enter your name:" #-n表示不换行read nameecho "Your name is $name"#-p选项允许直接在read命令行指定提示语read -p "Enter your name:" nameecho "Your name is $name"#如果不在read后指定变量,会将值保存在环境变量REPLY中read -p "Enter your name:" echo "Your name is $REPLY"#可以在read后指定多个变量read -p "Enter your content:" first lastecho $firstecho $last#假如你的输入是: first last1 last2 last3#输出是:#first#last1 last2 last3#指定超时read -t 5 -p "Enter your name:" name#此句的意思是如果超过5秒用户还没输入就继续执行不再等待#隐藏方式读取read -s -p "Enter your password:" password#-s选项会阻止用户的输入显示在显示器上(实际上,数据会被显示,只是-s选项#将输入的文本颜色设成和背景色一致,使用户看不到而已)#用read读取文件cat myfile | while read linedo    echo $linedone

9.控制脚本

常用linux信号

信号 值 说明 SIGHUP 1 挂起进程 SIGINT 2 终止进程 SIGQUIT 3 停止进程 SIGKILL 9 无条件终止进程 SIGTERM 15 可能的话终止进程 SIGSTOP 17 无条件停止进程,但不是终止进程 SIGTSTP 18 停止或暂停进程,但不是终止进程 SIGCONT 19 继续运行停止的进程

用trap命令捕捉信号

#trap的格式是:trap commands signals#一个例子trap "echo 'I receive signals'" SIGINT SIGTERM#在这个例子中,当脚本收到SIGINT或SIGTERM信号时就会输出#I receive signals#trap还可以捕捉shell脚本的退出trap "echo byebye" EXIT#移除捕捉trap - SIGINT EXIT

10.用select生成菜单

#一个例子#!/bin/bashdiskspace(){    clear    df -k}whoseon(){    clear    who}memusage(){    clear    cat /proc/meminfo}#设置提示语PS3="Enter option:"select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"do    case $option in    "Exit program")        break        ;;    "Display disk space")        diskspace        ;;    "Display logged on users")        whoseon        ;;    *)        clear        echo "Sorry,wrong selection"        ;;    esacdoneclear

11.数学运算

整数运算

a=10;b=5c=`expr $a + $b` #15let "c = $a - $b" #5c=$[ $a * $b ] #50c=$(( $a / $b )) #2 

浮点数运算

#shell本身不支持浮点数运算,但我们可以用bc实现#bc通过一个内建的称为scale的变量来控制小数位数#其默认值为0,bc还支持变量,注释,表达式,简单的控制语句,函数#由于我们是在脚本中使用,一般只用到变量和表达式功能#一个例子var1=`echo "scale=4;3.2/2" | bc`echo $var1 #1.6000#当表达式较长时可以用内联的输入重定向var1=10.46var2=43.67var3=33.2var4=71var5=`bc << EOFscale=4a1=($var1 * $var2) #这里的圆括号可以不要b1=($var3 * $var4)a1 + b1EOF`echo $var5 #2466.6116 

12.字段分隔符IFS

大家可以参考一下这个博客,讲得很详细
博客链接: Shell中的IFS解惑

0 0