2012年(21)
分类:
2012-11-21 00:20:35
原文地址:Linux shell编程笔记总结 作者:bjpiao
目 录
1、 Shell简介
1.1. 什么是shell
1.2. shell分类
2、 Shell语法
2.1. 定义变量
2.2. 变量类型
2.2.1. 字符集变量
2.2.2. 数字常量定义
2.2.3. 数组
2.2.4. 系统变量
2.3. 运算符与表达式
2.3.1. 运算符
2.3.2. 字符串表达式(判断条件命令if)
2.3.3. 字符串操作
2.3.4. 数值表达式
2.3.5. 复合条件表达式
2.4. 流程控制
2.4.1. 条件转移 :if 条件语句
2.4.2. 选择语句case
2.4.3. 循环语句
2.5. Shell中的函数运用
2.5.1. 函数声明
2.5.2. 局部变量
2.5.3. Shell脚本文件的参数
2.5.4. 函数的参数
2.6. 类型变量
2.6.1. declare 声明类型变量
2.7. Shell文件中的交互功能
2.8. 转义(\)
Linux Shell学习笔记
简介Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。
shell是用户和Linux内核之间的接口程序,如果把Linux内核想象成一个球体的中心,shell就是围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。
shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给Linux核心。
有一些命令,比如改变工作目录命令cd,是包含在shell内部的。还有一些命令,例如拷贝命令cp和移动命令rm,是存在于文件系统中某个目录下的单独的程序。对用户而言,不必关心一个命令是建立在shell内部还是一个单独的程序。
shell首先检查命令是否是内部命令,若不是再检查是否是一个应用程序(这里的应用程序可以是Linux本身的实用程序,如ls和rm,也可以是购买的商业程序,如xv,或者是自由软件,如emacs)。然后shell在搜索路径里寻找这些应用程序(搜索路径就是一个能找到可执行程序的目录列表)。如果键入的命令不是一个内部命令并且在路径里没有找到这个可执行文件,将会显示一条错误信息。如果能够成功找到命令,该内部命令或应用程序将被分解为系统调用并传给Linux内核。
shell的另一个重要特性是它自身就是一个解释型的程序设计语言,shell程序设计语言支持绝大多数在高级语言中能见到的程序元素,如函数、变量、数组和程序控制结构。shell编程语言简单易学,任何在提示符中能键入的命令都能放到一个可执行的shell程序中。
当普通用户成功登录,系统将执行一个称为shell的程序。正是shell进程提供了命令行提示符。作为默认值(TurboLinux系统默认的shell是BASH),对普通用户用“$”作提示符,对超级用户(root)用“#”作提示符。
一旦出现了shell提示符,就可以键入命令名称及命令所需要的参数。shell将执行这些命令。如果一条命令花费了很长的时间来运行,或者在屏幕上产生了大量的输出,可以从键盘上按ctrl+c发出中断信号来中断它(在正常结束之前,中止它的执行)。
当用户准备结束登录对话进程时,可以键入logout命令、exit命令或文件结束符(EOF)(按ctrl+d实现),结束登录。
Linux中的shell有多种类型,其中最常用的几种是Bourne shell(sh)、C shell(csh)和Korn shell(ksh)。三种shell各有优缺点。Bourne shell是UNIX最初使用的shell,并且在每种UNIX上都可以使用。Bourne shell在shell编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种shell。Linux操作系统缺省的shell是Bourne Again shell,它是Bourne shell的扩展,简称Bash,与Bourne shell完全向后兼容,并且在Bourne shell的基础上增加、增强了很多特性。Bash放在/bin/bash中,它有许多特色,可以提供如命令补全、命令编辑和命令历史表等功能,它还包含了很多C shell和Korn shell中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。
C shell是一种比Bourne shell更适于编程的shell,它的语法与C语言很相似。 Linux为喜欢使用C shell的人提供了Tcsh。Tcsh是C shell的一个扩展版本。Tcsh包括命令行编辑、可编程单词补全、拼写校正、历史命令替换、作业控制和类似C语言的语法,它不仅和Bash shell是提示符兼容,而且还提供比Bash shell更多的提示符参数。
Korn shell集合了C shell和Bourne shell的优点并且和Bourne shell完全兼容。Linux系统提供了pdksh(ksh的扩展),它支持任务控制,可以在命令行上挂起、后台执行、唤醒或终止程序。
shell语言是非类型的解释型语言,不象用C++/JAVA语言编程时需要事先声明变量.给一个变量赋值,实际上就是定义了变量.
由于shell程序的变量是无类型的,所以用户可以使用同一个变量时而存放字符时而存放数字。
在linux支持的所有shell中,都可以用赋值符号(=)为变量赋值.
如:
abc=9 (bash/pdksh不能在等号两侧留下空格 )
如:
name=abc (bash/pdksh)
在变量赋值之后,只需在变量前面加一个$去引用.
如:
echo $abc
字符集变量的声明方法是用双引号
如:
abc=”how are you ” (将字符集 how are you 赋值给abc)
echo $abc
输出结果:how are you
引用系统变量赋值
如:
abc=”$LOGNAME,how are you”; ($LOGNAME 存储了系统登录用户名)
echo $abc
输出结果:root,how are you
字符串相加
abc=” how are you”” root”
echo $abc
输出结果:how are you root
十进制:直接写数字
如:a=12 #a是十进制12
八进制:在前面加0
如:a=012 #a是八进制12
十六禁止:在数字前加0x
如:a=0x12 #a是十六进制12
数组下标是以零为开始;
数组的使用方法
如:
arr1=(1 2 3 4 5) # 定义数组arr1,并初始化5个值
echo ${arr1[0]} #打印数组中第零个变量值
arr1[0]=6 #将数组中第0个值赋值为6
echo ${arr1[0]} #打印数组中第零个变量值
系统变量就是环境变量,系统变量定义后可以直接在操作系统中调用,对于不同的用户,其所有的系统变量也不同;
系统变量用export声明,如:
export varname=”system var” #声明varname 为系统变量;
可以在操作系统提示符下直接访问varname
如:#echo $varname
执行结果:system var
算术运算符
+ 加法
- 减法
* 乘法
/ 除法
** 幂运算
let "z=5**3"
echo "z = $z" # z = 125
% 取模
+= 加等于(通过常量增加变量)
如:let "var += 5" #var将在本身值的基础上增加5
-= 减等于
*= 乘等于
如:let "var *= 4"
/= 除等于
%= 取模赋值,
算术操作经常使用expr或者let表达式
逻辑运算符
|| 逻辑或
&& 逻辑与
Str1 = str2 当str1与str2相同时,返回True
Str1! = str2 当str1与str2不同时,返回True
Str 当str不是空字符时,返回True
-n str 当str的长度大于0时,返回True
-z str 当str的长度是0时,返回True
例如:文件b.sh如下
#!/bin/bash
A1="abc"
B1="abc"
C1="abcde"
if [ "$A1" = "$B1" ]
then
echo "A1=B1"
fi
if [ "$A1" != "$C1" ]
then
echo "A1<>C1"
fi
if [ -n "$A1" ]
then
echo "$A1 length>0"
fi
输出结果:
A1=B1
A1<>C1
abc length>0
得到字符串长度,使用方法:expr length para
#para代表字符串变量
截取字符串,使用方法:${para:X1:X2}
#para代表字符串变量参数,X1代表截取位置,X2代表截取长度,可省略
子串删除,使用方法:{string#substring}
#从string中删除第一个子串substring;
子串替换,
${string/substring/replacement}
使用$replacement来替换第一个匹配的$substring.
${string//substring/replacement}
使用$replacement来替换所有匹配的$substring.
如文件b.sh
#!/bin/bash
string1=teststring
expr length $string1 #字符串长度
echo ${string1:0} #输出字符串
echo ${string1:1} #输出子字符串,从第二个字符开始到字符串结尾
echo ${string1:1:3} #输出第1至3个字符
echo ${string1#test} #删除字符串中的test子串
echo ${string1/test/replace} #将字符串中的子串test替换为replace
输出结果:
10
teststring
eststring
est
string
Int1 -eq int2 #当int1等于int2时,返回True
Int1 -ge int2 #当int1大于/等于int2时,返回True
Int1 -le int2 #当int1小于/等于int2时,返回True
Int1 -gt int2 #|当int1大于int2时,返回True
Int1 -ne int2 #当int1不等于int2时,返回True
实例:如下文件 b.sh
#!/bin/bash
int1=3
int2=4
if [ $int1 -eq $int2 ]
then
echo "int1=int2"
else
echo "int1<>int2"
fi
执行结果:
Int1<>int2
实例:如文件b.sh
#!/bin/bash
int1=3
int2=4
if [ $int1 -ge 1 ] && [ $int2 -le 7 ]
then
echo "int1>=1 and int2<=7"
fi
if [ $int1 -ge 1 ] || [ $int2 -le 1 ]
then
echo "int1>=1 or int2<=1"
fi
执行结果:
int1>=1 and int2<=7
int1>=1 or int2<=1
语法:
if [ 条件 ]
then #符合条件
表达式
else #不符合条件
表达式
fi #结束条件
详细例子在本文档中各实例中均有介绍
如文件:b.sh
#!/bin/bash
a1=2;
case $a1 in
1)
echo "a1=1";;
2)
echo "a1=2";;
esac
执行结果:a1=2
|
|
|
实例:b.sh | 实例:b.sh | 实例:b.sh |
1 |
1 |
1 |
函数声明:
Function_name() #声明函数
{
command #函数的主体,执行的命令;
}
例如:b.sh
#!/bin/bash
testfunction() #函数声明和处理过程
{
echo "this is a test function"
}
testfunction #函数调用
执行结果:this is a test function
函数中的局部变量用local声明,变量的作用范围是本函数内部,函数执行完毕后局部变量被删除;
如下实例b.sh
#!/bin/bash
abc=112233 #声明全局变量abc
localpara() #定义函数
{
local abc=123 #定义局部变量abc,注意区分上面的abc
echo "local para abc is $abc" #输出局部变量
}
localpara #调用函数,输出局部变量abc
echo "abc is $abc" #输出全局变量abc,变量值没有改变
执行结果:
local para abc is 123
abc is 112233
文件参数
在shell脚本中使用参数的方法如下:
./b.sh start #start 就是第一个参数
调用方法:
./b.sh test1 输出结果是:this is runpara1
./b.sh test2 输出结果是:this is runpara2
特殊的文件参数
$0 脚本程序名称
$n 程序文件的第n个参数
$* 程序文件的所有参数
$# 程序文件参数的个数
$$ 程序文件执行时的PID
看如下脚本文件b.sh
#!/bin/bash
runpara1() #函数声明
{
echo "this is runpara1"
}
runpara2() ##函数声明
{
echo "this is runpara2"
}
if [ $# -gt 0 ]
then
echo “para count >0”
fi
case $1 in # $1 代表第一个参数的值
test1) #如果参数是test1就执行函数runpara1
runpara1
;;
test2)
runpara2
;;
esac
如下文件 b.sh
#!/bin/bash
testfunction () #声明函数
{
if [ -z "$1" ] #判断函数是否存在参数($1)
then
echo "no para in function" #无参数处理过程
else
echo "function's paraname is "$1"" #有参数处理过程
fi
}
testfunction start #执行函数,函数的参数是start
执行结果:function’s paraname is start
declare –r abc=”test string” #声明abc是只读类型
declare –i int1 #声明int1是整数类型
declare –a arr1 #声明arr1为数组变量
declare -f 函数名(可选) #当存在函数名时,只会列出文件中的名称是所写函数的定义,如果不存在函数名,则列出所有函数的声明
看下面的例子b.sh:
#!/bin/bash
declare -r abc="test declare" #声明只读变量abc
echo "echo $abc"
abc="read only" #将会出现错误提示,因为abc是只读变量
echo "echo $abc" #打印abc变量,还是“test declare”没有变化
declare -i int1 #声明整型变量int1
int1=12;
int1="test string" #给整型赋值为字符串,错误
echo "$int1"
int1=int1/3 #整型变量可以直接使用操作符/
echo “$int1”
func1() #声明函数func1
{
echo "test function"
}
func2() #声明函数func2
{
echo "test function"
}
declare –f #显示所有函数
declare -f func1 #显示函数func1
文件的执行结果如下:
echo test declare
./b.sh: abc: readonly variable #只读变量错误提示
echo test declare
./b.sh: test string: syntax error in expression (error token is "string") #变量类型错误
12
4 #显示的是 12/3的结果
declare -f func1 () #显示所有函数
{
echo "test function"
}
declare -f func2 ()
{
echo "test function"
}
func1 () #显示函数func1
{
echo "test function"
}
程序需要对用户输入的字符进行判断后执行相应的操作
如下面的文件b.sh
#程序完成的功能是,判断用户输入的名称,如果用户输入的名称不是zhangwei,就继续提示输入,如果用户输入了zhangwei,就提示欢迎字符,程序退出;
#!/bin/bash
while :
do
echo -n "please input you name:" #提示用户输入
read line #读取用户输入的数据
if [ "$line" = "zhangwei" ] #判断用户输入的数据
then
echo "welcome $line" #显示欢迎信息
exit
fi
done
转义是一种引用单个字符的方法.一个具有特殊含义的字符前边放上一个转义符(\)就告诉shell这个字符失去了特殊的含义.
对于特定的转义符的特殊的含义(在echo和sed中所使用)
\n 换行
\r 回车
\t tab键
\v vertical tab(垂直tab),查前边的Ctl-K
\b backspace,查前边的Ctl-H
\a "alert"(如beep或flash)
\0xx 转换成8进制ASCII解码,等价于oxx
实例,使用转义符“\”
看下文件b.sh
#!/bin/bash
echo "\v\v\v\v" # 打印字符串”\v\v\v\v .”
echo -e "\v\v\v\v" #打印4个垂直tab
echo $’\v\v\v\v’ #打印4个垂直tab
echo –e “\101” #打印出A,因为A是101的八进制的ascII
echo \z #输出 z
echo '\z' #输出 \z
echo \\z #输出 \z