一、Linux简介
二、deb软件包管理
三、shell中的特殊字符
四、Linux常用命令
五、shell编程
目录
一、shell与变量
1.shell脚本基础知识
2.shell变量
2.1 用户自定义变量
2.2 位置变量(命令行参数)
2.3 预定义变量
2.4 环境变量
二、shell语句
1.常用功能性语句
1.1 read命令
1.2 expr命令
2.测试语句
test
3.结构性语句
3.1条件语句
3.2多路分支语句
3.3循环语句for
3.4循环语句while
3.5循环控制语句
三、函数
1.shell函数调用
2.函数变量作用域
编程语言分为编译型语言和解释型语言,shell脚本语言是解释型语言。
shell脚本本质上就是shell命令的有序集合。
shell编程的基本过程分为三步:
①建立shell文件:包含任意多行操作系统命令或shell命令的文本文件;
②赋予shell文件执行权限:用chmod命令修改权限;
③执行shell文件:直接在命令行上调用shell程序
shell允许用户建立变量存储数据,但不支持数据类型(整型、字符、浮点型),将任何赋给变量的值都解释为一串字符
count=1 #这里的等号前后不要加空格,否则会报错
echo $count
DATE=`date` #这里的等号前后不要加空格
echo $DATE
Bourne Shell(以.sh为后缀)有如下四种变量:
用户自定义变量一般全大写,方便识别
COUNT=1
在变量前加$调用变量
echo $HOME
使用unset命令删除变量的赋值
Z=hello
echo $Z
unset Z
echo $Z
$0 :与键入的命令行一样,包含脚本文件名
$1,$2,.......$9,${10}.....: 分别包含第一个到第十个命令行参数
$#: 包含命令行参数的个数(不包含$0)
$@: 包含所有命令行参数(不包含$0)
$?: 包含前一个命令的推出状态(0表示正常退出)
$*: 包含所有命令行参数(不包含$0)
$$: 包含正在执行的进程ID号
常用的shell环境变量
HOME:/etc/passwd 文件中列出的用户主目录
IFS:Internal Field Separator,默认为空格,tab及换行符
PATH:shell搜索路径
PS1,PS2:默认提示符($)及换行提示符(>)
TERM:终端类型,常用的有vt100,ansi,vt200,xterm等
shell语句包括三类:1.说明性语句,2.功能性语句,3.结构性语句。
其中,说明性语句以#号开始到该行结束,不被解释执行;功能性语句是任意的shell命令,用户程序或其他shell程序;结构性语句包括条件测试语句、多路分支语句、循环语句、循环控制语句等。
任意的shell命令、用户程序或其他shell程序
read从标准输入读入一行,并赋值给后面的变量,其语法为
read var
#把读入的数据全部赋给var(空格隔开)
read var1 var2 var3
#如果执行read语句时标准输入无数据,则程序在此停留等候,直到数据的到来或被终止运行
# example1 for read
echo "Input your name: \c"
read username
echo "Your name is $username“
# example2 for read
echo "Input date with format yyyy mm dd: \c"
read year month day
echo "Today is $year/$month/$day, right?"
echo "Press enter to confirm and continue\c"
read answer
echo "I know the date, bye!"
主要用于进行简单的整数运算,包括加(+)、减(-)、乘(\*),整除(/)和求模(%)等操作,例如
> expr 12 + 5 \* 3 # 反斜线去掉*号的元字符含义
27
> expr 3 - 8 / 2 # 运算符号前后要加空格
-1
> num=9
> sum=`expr $num \* 6` # 反撇号引用命令的运行结果
> echo $sum
54
test语句可测试三种对象: ①字符串 ②整数 ③文件属性
每种测试对象都有若干测试操作符,例如:
test "$answer" = "yes"# 变量answer的值是否为字符串yes
test $num –eq 18 # 变量num的值是否为整数18
test -d tmp #测试tmp是否为一个目录名
字符串测试
s1 = s2 测试两个字符串的内容是否完全一样
s1 != s2 测试两个字符串的内容是否有差异
-z s1 测试s1 字符串的长度是否为0
-n s1 测试s1 字符串的长度是否不为0
整数测试
a -eq b 测试a 与b 是否相等(equal)
a -ne b 测试a 与b 是否不相等(not equal)
a -gt b 测试a 是否大于b(great than)
a -ge b 测试a 是否大于等于b(great equal)
a -lt b 测试a 是否小于b(less than)
a -le b 测试a 是否小于等于b
文件测试
-d name 测试name 是否为一个目录
-e name 测试一个文件是否存在
-f name 测试name 是否为普通文件
-L name 测试name 是否为符号链接
-r name 测试name 文件是否存在且为可读
-w name 测试name 文件是否存在且为可写
-x name 测试name 文件是否存在且为可执行
-s name 测试name 文件是否存在且其长度不为0
f1 -nt f2 测试文件f1 是否比文件f2 更新
f1 -ot f2 测试文件f1 是否比文件f2 更旧
结构性语句主要根据程序的运行状态、输入数据、变量的取值、控制信号以及运行时间等因素来控制程序的运行流程。
主要包括:条件测试语句(两路分支)、多路分支语句、循环语句、循环控制语句和后台执行语句等。
这里要注意,在shell中条件为真返回的是0而不是1,那么对于判断符[] 来说,只要符号里面的内容为真即为成功,不要用0 1去理解,容易混肴。
if…then…fi
语法结构:
if 表达式
then 命令表
fi
#The statement of if…then…fi (注释语句)
if [ -f $1 ] (测试参数是否为文件)
then
echo "File $1 exists" (引用变量值)
fi
if [ -d $HOME/$1 ] (测试参数是否为目录)
then
echo "File $1 is a directory" (引用变量值)
fi
if...then...else...fi
语法结构:
if 表达式
then 命令表1
else 命令表2
fi
如果表达式为真, 则执行命令表1中的命令, 再退出if语句; 否则执行命令表2中的语句, 再退出if语句.
注意: 无论表达式是否为真, 都有语句要执行.
###test命令测试的条件成立时, 命令返回值为真(0),否则返回值为假(非0).
#方式1
test $name -eq $1
echo $?
#方式2
if test -f $filename
then
......
fi
#方式3,用方括号代替test语句
if [ -f $filename ] #方括号的首末至少要有一个空格
then
......
fi
case......esac
语法结构:
case 字符串变量 in #case语句只能检测字符串变量
模式1) #各模式中可用文件名元字符,以右括号结束
命令表1
;;
模式2|模式3) #一次可以匹配多个模式,用“ | ”分开
命令表2
;; #命令表以单独的双分号行结束,推出case语句
......
模式n) #模式n常写为字符* 表示所有其他模式
命令表n
;; #最后一个双分号行可以省略
esac
实例:
# The statement of case…esac
if [ $# -eq 0 ]
then
echo "No argument is declared"
exit
fi
case $1 in
file1)
echo "User selects file1"
;;
file2)
echo "User selects file2"
;;
*)
echo "You must select either file1 or file2!"
;;
esac
语法格式:
for 变量名 in 单词表
do
命令表
done
变量依次取单词表中的各个单词, 每取一次单词, 就执行一次循环体中的命令. 循环次数由单词表中的单词数确定. 命令表中的命令可以是一条, 也可以是由分号或换行符分开的多条。行符分开的多条。
如果单词表是命令行上的所有位置参数时, 可以在for语句中省略 “in 单词表” 部分。
实例:拷贝当前目录下的所有文件到backup子目录下
# The statement of for…do…done
if [ ! -d $HOME/backup ]
then
mkdir $HOME/backup
fi
flist=`ls` #flist的值是ls的执行结果即当前目录下的文件名
for file in $flist
do
if [ $# = 1 ]
then
if [ $1 = $file ] #命令行上有一个参数时
then
echo "$file found" ; exit
fi
else #命令行上不带参数时
cp $file $HOME/backup
echo "$file copied"
fi
done
echo ***Backup Completed***
语法结构:
while 命令表达式
do
命令表
done
while语句首先测试其后的命令或表达式的值,如果为真,就执行一次循环体中的命令,然后再测试该命令或表达式的值,执行循环体,直到该命令或表达式为假时退出循环。
while语句的退出状态为命令表中被执行的最后一条命令的退出状态。
实例:根据输入批量生成空白文件
# The statement for while
if [ $# = 2 ]
then
loop=$2 #根据命令行的第二个参数来确定循环的次数
else
loop=5
fi
i=1
while [ $i -lt $loop ]
do
> $1$i #建立以第一个参数指定的文件名前缀,例如以“file”开头, 变量i的值结尾的空文件名.
#参见命令cmd > file
i=`expr $i + 1`
done
break和continue
break n :跳出n层循环
continue:马上转到最近一层循环语句的下一轮循环上
continue n:转到最近n层循环语句的下一轮循环上。
实例,检查输入参数中的偶数值,并打印
#!/bin/bash
if [ $# = 0 ]
then
echo "Numeric arguments required"
exit
fi
if [ $# -gt 10 ]
then
echo "Only ten arguments allowed"
exit
fi
for number #省略了‘in 单词表’ ,表示number依次取命令行上的所有位置参数
do
count=`expr $number % 2` #count值只能是0或1
if [ $count -eq 1 ]
then
continue
else
output="$output $number" #这样就能输出一个队列了
fi
done
echo "Even numbers: $output "
方式1:
value_name=`function_name [arg1 arg2 … ]`
函数的所有标准输出都传递给了主程序的变量
方式2:
function_name [arg1 arg2 … ]
echo $?
获取函数的返回的状态
实例
check_user( ) { #查找已登录的指定用户
user=`who | grep $1 | wc -l` #等号两端不能留空格,否则会有警告,具体见shell中的空格
if [ $user –eq 0 ]
then
return 0 #未找到指定用户
else
return 1 #找到指定用户
fi
}
while true # MAIN, Main, main: program begin here
do
echo "Input username: \c"
read uname
check_user $uname # 调用函数, 并传递参数uname
if [ $? –eq 1 ] # $?为函数返回值
then echo "user $uname online"
else echo "user $uname offline"
fi
done
其中,' | '是管道符,将' | '前面命令的输出作为'|'后面的输入。
who命令用于显示系统中有哪些使用者正在上面,显示的资料包含了使用者 ID、使用的终端机、从哪边连上来的、上线时间、呆滞时间、CPU 使用量、动作等等。
grep命令用于查找文件里符合条件的字符串。
wc指令我们可以计算文件的Byte数、字数、或是列数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据。属性:-l或--lines 显示行数。
全局作用域:在脚本的其他任何地方都能够访问该变量。
局部作用域:只能在声明变量的作用域内访问。
声明局部变量的格式:
Local variable_name = value
实例
Scope()
{
Local lclvariable =1
Gblvariable = 2
echo “lclavariable in function = $ lclvariable ”
echo “Gblvariable in function = $ Gblvariable ”
}
Scope
echo “lclavariable in function = $ lclvariable ”
echo “Gblvariable in function = $ Gblvariable ”