shell 基本编程

shell 变量

shell 变量类型

shell 中变量的类型分为:本地变量、环境变量、位置变量、特殊变量;

环境变量

环境变量是用于设置系统运行环境的变量,在 shell 的所有用户进程可用,通常称之为全局变量;环境变量的名称一般是由大写字母组成,例如:

#HOME变量,用户主目录的全路径名;
echo $HOME

#PATH变量,定义一些目录路径;
echo $PATH

#PWD变量,当前工作目录的绝对路径;
echo $PWD

位置变量

位置变量是依据出现在命令行上的参数的位置来确定的变量,通常被 shell 脚本用来从命令行接受参数,或被函数用来保存传递给它的参数。执行 shell 脚本时,用户可以通过命令行向脚本传递信息,跟在脚本名后面的用空格隔开的每个字符串都称为位置变量。如下所示:

$命令 参数1 参数2 参数3 ...

具体有如下的位置变量:

位置变量 具体含义
$0 当前执行的命令或shell程序的文件名
$1 表示第1个位置参数
$2 表示第2个位置参数
$9 表示第9个位置参数
${10} 从第10个参数开始必须使用大括号

例如:

#!/bin/bash
#filename:test.sh
echo "shell程序文件名为: $0"
echo "第1个位置参数: $1"
echo "第2个位置参数: $2"
echo "第3个位置参数: $3"
echo "第4个位置参数: $4"
echo "第5个位置参数: $5"

执行test.sh文件:

$ sh test.sh linux shell bash learn ubuntu
shell程序文件名为: test.sh
第1个位置参数: linux
第2个位置参数: shell3个位置参数: bash
第4个位置参数: learn
第5个位置参数: ubuntu

特殊变量

特殊变量与环境变量相类似,由 shell 根据实际情况来设置,这些变量具有特殊的含义,用户不能重新设置该值,所有特殊变量都由$符号与另一个符号组成,常见的特殊变量如下表所示:

特殊变量 具体含义
$# 实际位置参数的个数
$* 命令行中所有位置参数组成的字符串
$! 上一个后台命令对应的进程ID号
$$ 表示当前运行脚本的进程ID号
$? 表示最后命令运行后的退出状态

本地变量

本地变量是用户自定义的变量,变量的命名规则跟其他高级语言类似,必须以字母或下划线开头,后面接字母、下划线或数字;变量名对大小写字母敏感。局部变量定义格式如下:

local 变量名

变量的操作

创建和设置变量

shell中有两个内置命令 declare 和 typeset 可用于创建变量,通过命令的选项设置可以设定变量的创建方式,例如declare -r创建只读变量;

declare attribute 变量名

其中attribute表示属性,取值如下表所示:

属性 具体含义
-p 显示所有变量的值
-i 定义整数变量
-r 定义只读变量
-a 定义数组变量
-f 显示所有自定义函数
-x 将变量设置为环境变量

除了两个内置命令外,也可通过直接赋予一个变量名来创建变量,为变量赋值时,变量前不必加$符号,只有在使用该变量时才会使用$符号;变量的创建如下:

变量名=变量值

注意:等号=两边不能有空格,变量值内部有空格时,该变量值必须使用双引号;变量名不能与其他文字混在一起,若想要在变量名紧接文字时,必须使用大括号把变量名包起来;例如:

#!/bin/bash
#filename:test.sh
var=10  #变量var
y="usage [d] shell" #变量y
x=20
#显示变量的值
echo "the value of var is: $var"
echo "the value of y is: $y"
echo "the value of x is: ${x}th"

执行结果:

$ sh test.sh
the value of var is: 10
the value of y is: usage [d] shell
the value of x is: 20th

shell 支持三种引号方式:

  1. 单引号:单引号内的字符都作为普通字符;
  2. 双引号:除了$、\、'、"这几个特殊符号保留其特殊功能之外,其他字符仍作为普通字符;
  3. 反引号:反引号内的字符被解析为命令;

删除变量

使用shell的内部 unset 命令可以删除变量。语法:

unset variable_name

变量被删除后不能再次使用;unset 命令不能删除只读变量。例子:

#!/bin/sh
#filename:test.sh
var="http://blog.csdn.net/chenhanzhun"
echo -n "before use unset,the value of var:"
echo $var
unset var
echo -n "after use unset,the value of var:"
echo $var

执行结果:

$ sh test.sh
before use unset,the value of var:http://blog.csdn.net/chenhanzhun
after use unset,the value of var:

变量的赋值

直接赋值

在shell 程序中,在定义变量的同时直接赋予初值;例如:

#!/bin/sh
#filename:test.sh
#直接给变量赋值
var="http://blog.csdn.net/chenhanzhun"

使用 read 命令赋值

read 是 shell 的内部命令,可以从标准输入设备或从一个文件读取数据,read 命令读取一个输入行直到遇到换行符为止,其语法格式如下:

#把读入的数据依次赋值给:变量1、变量2、变量3、...
read  变量1  变量2  变量3  ...

read 命令的赋值规则如下:

  1. 多个输入数据或变量之间使用空格分开;
  2. 若变量个数与输入数据个数相等,则对应赋值;
  3. 若变量个数大于输入数据个数,则没有输入数据的变量赋值为空;
  4. 若变量个数小于输入数据个数,则多于的输入数据都赋值给最后一个变量;

若没有指定变量来保存 read 所输入的内容,则 bash 会把输入的数据保存在 REPLY 的变量中,另外 read 加上参数 -p 可以提示信息,即read -p
例如:

#!/bin/sh
#filename:test.sh
echo -n "please enter your name and telephone number: "
read var1 var2
echo -n "you had enter your name are: "
echo $var1
echo -n "you had enter your NO. is: "
echo $var2

read -p "the second, enter the value: "
echo -n "you had enter the value is: $REPLY"

执行结果:

$ sh test.sh
#情况1:变量个数与输入数据个数相等
please enter your name and telephone number: Linux 123456
you had enter your name are: Linux
you had enter your NO. is: 123456

#情况2:变量个数大于输入数据个数
please enter your name and telephone number: Linux
you had enter your name are: Linux
you had enter your NO. is: 

#情况3:变量个数小于输入数据个数
please enter your name and telephone number: Linux 123456 shell 789
you had enter your name are: Linux
you had enter your NO. is: 123456 shell 789

#使用 -p 选项,并使用默认变量 REPLY
the second, enter the value: 16
you had enter the value is: 16

命令行参数赋值

在 shell 中可以使用命令行参数给位置变量赋值;例如:

#!/bin/sh
#filename:test.sh
echo "first: $1"
echo "second: $2"
echo "third: $3"

#执行结果如下:
$ sh test.sh Linux Nginx C++
first: Linux
second: Nginx
third: C++

变量的输出

变量的输出由echoprintf命令完成,printf命令跟 C语言的类似,也可以格式化输出;

数组变量

数组的定义

数组的定义格式如下所示:

数组名=(元素1 元素2 元素3 ...)
#例如:定义一个student数组
student=(one two three four)

例子:

#!/bin/bash
#filename:test.sh

student=(one two three four)
for i in 0 1 2 3
do
echo ${student[$i]}
done

#执行结果:
$ sh test.sh
one
two
three
four

数组引用

${arr[num]} #数组下标为 num 的元素
${#arr[*]} #数组元素的个数
${#arr[num]} #数组下标为 num 的元素的长度
all=("${arr[*]}") #将数组arr的全部内容作为一个元素复制给数组all
all=("${arr[@]}") #将数组arr的全部内容复制给数组all

算术运算

shell 中没有内置算术运算,不能直接做加、减、乘、除等算术运算;整数运算可以使用expr命令或let命令;浮点运算可以使用awk命令或bc命令。

整数运算

expr 命令

expr命令是一个表达式处理命令,当用来计算算术运算表达式时,它可以执行简单的整数操作,有 5 中算术运算符可以使用:+、-、\*、/、%;在使用这些运算符时,运算符前后必须有空白,且只能用于整数运算;例如:

#!/bin/bash
#filename:test.sh

var=10
a=5
x=`expr $var / $a`
y=`expr $var % $a`
b=`expr $a + 4`

echo x=$x y=$y b=$b

#执行结果:
$ sh test.sh
x=2 y=0 b=9

let命令

let命令不需要在变量前面加$符号,但必须将单个或带有空格的表达式用双引号引起来。例如:

#!/bin/bash
#filename:test.sh

var=10
a=5
let x=var/a
let y=var%a
let "b = a + 4"
c=`expr $a \* $var`

echo x=$x y=$y b=$b c=$c

#执行结果:
$ sh test.sh
x=2 y=0 b=9 c=50

浮点运算

bc命令
例子:

#!/bin/bash
#filename:test.sh
n=`echo " scale=2; 172 / 2 " | bc `
echo $n
#执行结果:
86.00

#解析:
#反单引号:把反单引号里面的字符作为命令执行;
#scale=2 表示设置小数点后面保留2位;
#echo的结果通过管道命令传入给bc命令

awk命令
例子:

#!/bin/bash
#filename:test.sh
var=` awk 'BEGIN {x=5.1;y=2; printf "%.2f %.3f" , x*y,x/y;}'`
echo $var

#执行结果:
$ sh test.sh
10.20 2.550

条件测试

shell 脚本中提供了对数值、字符和文件的条件测试,测试结果若为0表示条件为真,若为非0表示条件为假。

shell 的测试命令

条件测试有两种语法:test命令和[]命令;test 命令是shell 编程中条件判断最常用的测试命令,一般与if、while、until命令一起使用,test命令格式如下:

test 表达式
#test 命令也可以使用方括号代替,注意:方括号前后必须有空格
[ 表达式 ]

#例如:
x=5;y=8
test $x -gt $y
echo $?
[ $x -gt $y ]
echo $?

#执行结果:
$ sh test.sh
1
1

文件测试

文件属性测试表达式是测试文件的属性状态,包括文件是否可写、可执行,文件是否存在;常用的文件测试表达式如下:

表达式 具体含义
-b FILE FILE exists and is block special
-c FILE FILE exists and is character special
-d FILE FILE exists and is a directory
-e FILE FILE exists
-f FILE FILE exists and is a regular file
-g FILE FILE exists and is set-group-ID
-G FILE FILE exists and is owned by the effective group ID
-h FILE FILE exists and is a symbolic link (same as -L)
-k FILE FILE exists and has its sticky bit set
-L FILE FILE exists and is a symbolic link (same as -h)
-O FILE FILE exists and is owned by the effective user ID
-p FILE FILE exists and is a named pipe
-r FILE FILE exists and read permission is granted
-s FILE FILE exists and has a size greater than zero
-S FILE FILE exists and is a socket
-t FD file descriptor FD is opened on a terminal
-u FILE FILE exists and its set-user-ID bit is set
-w FILE FILE exists and write permission is granted
-x FILE FILE exists and execute (or search) permission is granted

例如:

#!/bin/bash
#filename:test.sh

echo -n "please enter the filename: "
read FILENAME

#测试文件是否存在
if test -e $FILENAME ; then
    ls -l $FILENAME
else
    touch $FILENAME
fi

#测试文件是否可执行
if test -x $FILENAME ; then
    sh $FILENAME
else
    chmod +x $FILENAME
    ls -l $FILENAME
fi

#其他文件属性的测试类似上面

#执行结果
$ sh test.sh
please enter the filename: test.sh
-rw-rw-r-- 1  354 Mar  7 10:09 test.sh
-rwxrwxr-x 1  354 Mar  7 10:09 test.sh

数值测试

数值测试包括:相等、不相等、大于、小于、不大于、不小于;常用的数值测试表达式如下表所示:

表达式 具体含义
var1 -eq var2 var1等于var2
var1 -ne var2 var1不等于var2
var1 -gt var2 var1大于var2
var1 -lt var2 var1小于var2
var1 -ge var2 var1大于等于var2
var1 -le var2 var1小于等于var2

例如:

#!/bin/bash
#filename:test.sh

echo -n "please enter two number: "
read N1 N2

if test $N1 -eq $N2 ; then
    echo "equal"
elif test $N1 -gt $N2 ; then
    echo "greater"
else
    echo "less"
fi

#执行结果:
$ sh test.sh
please enter two number: 15 20
less

字符测试

字符测试包括:相等、不相等、长度是否为0、非空测试;常用的字符测试表达式如下表所示:

表达式 具体含义
-z str str长度为0
-n str str长度不为0
str1 = str2 str1 等于 str2
str1 != str2 str1 不等于 str2
str str不为空

例如:

#!/bin/bash
#filename:test.sh

echo -n "please enter str1: "
read str1

echo -n "please enter str2: "
read str2
if test $str1 = $str2; then
    echo "equal"
else
    echo "not equal"
fi

if test -z $str1; then
    echo "the length of str1 is 0"
else
    echo "the length of str1 is not 0"
fi

if test $str2; then
    echo "str2 is not empty"
else
    echo "str2 is empty"
fi

#执行结果:
$ sh test.sh
please enter str1: Linux
please enter str2: shell
not equal
the length of str1 is not 0
str2 is not empty

逻辑测试

当测试命令由多个测试条件构成时,必须使用到逻辑符号进行测试,shell 提供了:非(!)、与(-a)、或(-o)逻辑运算符,其优先级一次递减:!、-a、-o;
例子:

#!/bin/bash
#filename:test.sh

echo -n "please enter the number: "
read a

if test $a -ge 10 -a $a -le 20; then
    echo "10<= $a <=20"
else
    echo "not between 10~20"
fi

#执行结果:
$ sh test.sh
please enter the number: 12
10<= 12 <=20

shell 的控制结构

shell 提供了对多种流程控制结构的支持,包括:条件结构、分支结构、循环结构;

条件结构

在shell中使用 if语句来实现条件结构,其语法格式如下所示:

if 表达式
then
    执行语句
elif 表达式;then #then与表达式在同一行时,必须在表达式后面加上分号
    执行语句
elif 表达式
then
    执行语句
else
    执行语句
fi

#嵌套if语句

if 表达式;then
    执行语句
else
    if 表达式; then
            执行语句
    elif 表达式; then
            执行语句
    else
            执行语句
    fi
fi

其中,表达式是判断条件,若为真时,才执行 then里面的执行语句;if语句可以嵌套if语句,嵌套语句相当于elifif语句里面可以包含多个elif,但是只能有一个else语句;

分支结构

分支结构case 语句是一个多路分支判断结构,可以测试一个表达式的值,并根据该值选择执行相应的分支程序;其语法格式如下所示:

case 表达式 in
    模式1) 执行语句;; #若匹配到模式1时,先执行语句,然后 ;; 跳出case 语句
    模式2) 执行语句;;
    模式3) 执行语句;;
    ...
    *) 执行语句;; #若上面的模式都不匹配时,则执行这里的语句
esac #结束case语句

#注意:case 语句和 if语句一样,也可以嵌套使用

循环结构

select 循环结构
select循环结构的语法格式如下所示:

select 变量 in 列表
do
    执行语句
done

列表是由字符串组成的序列,执行select 语句时,该列表会以菜单形式进行显示,用户选择其中某一项之后,shell 会把该项赋值给变量,并执行select结构体中的语句。例如:

#!/bin/bash
#filename:test.sh

echo "select the number: "

select N in one two three foure five six seven
do
    case $N in
        one) echo "one";;
        two) echo "two";;
        three) echo "three";;
        foure) echo "foure";;
        five) echo "five";;
        six) echo "six";;
        seven) echo "seven";;
        *) echo "none"
        break;;

esac
done

#执行结果:
$ sh test.sh
select the number: 
1) one
2) two
3) three
4) foure
5) five
6) six
7) seven
#? 1
one
#? 5
five
#? 8
none

while 循环结构
while循环结构的语法格式如下所示:

while 表达式
do
    执行语句
done

#注意:while 语句里面可以嵌套 while 语句

例如:

#!/bin/bash
#filename:test.sh

echo "while:  "
i=1
while [ $i -le 5 ]
do
    echo "the ${i}th while;"
    i=$(($i+1))
done

#执行结果
$ sh test.sh
while:  
the 1th while;
the 2th while;
the 3th while;
the 4th while;
the 5th while;

for 循环结构
for语句的语法格式如下所示:

for 变量 [ in 列表 ]
do
    执行语句
done

例如:

#!/bin/bash
#filename:test.sh

echo "while:  "

for i in 1 2 3 4
do
    echo "the ${i}th while;"

done

#执行结果:
$ sh test.sh
while:  
the 1th while;
the 2th while;
the 3th while;
the 4th while;

until 循环结构
until循环结构是当条件为假时,执行语句,条件为真时,停止执行;其语法格式如下所示:

until
    执行语句
test 表达式
do
    执行语句
done

例如:

#!/bin/bash
#filename:test.sh

echo -n "enter the number:  "
read N
i=1

until
    test $i -gt $N
do
    result=`expr $i \* $i`
    echo "$i------$result"
    i=$(($i+1))
done

#执行结果:
$ sh test.sh
enter the number:  5
1------1
2------4
3------9
4------16
5------25

函数

函数定义

函数的定义格式如下所示:

function 函数名 ()
{
    执行语句
}
#或
函数名()
{
    执行语句
}

函数调用

函数调用格式如下所示:

函数名 参数1 参数2 ...

例如:

#!/bin/bash
#filename:test.sh

#定义函数
getcurrenttime()
{
    curr_time=`date`
    echo "$curr_time"
}

function show()
{
    echo $a $b $c
    echo $1 $2 $3
}
a=10
b=12
c=13
#调用函数
getcurrenttime
#调用函数并传递参数
show a b c

#执行结果:
$ sh test.sh
Sat Mar  7 16:00:38 CST 2015
10 12 13
a b c

若在函数想要返回值时,可使用returnreturn返回值只能是0~256之间的一个整数,返回值保存在变量$?中,若没有指定return返回值,则返回的函数值是该函数最后一个执行命令的退出状态;

删除函数

使用命令unset -f可以从 shell 内存中删除函数,其格式如下所示:

unset -f 函数名

你可能感兴趣的:(shell)