shell常识
shell本身是用C语言编写的程序,它为用户使用Linux系统提供了便捷。shell既是一种命令语言,又是一种程序设计语言。它虽然不是Linux系统核心的一部分,但它调用了系统核心的大部分功能来执行程序,建立文件以并行的方式来协调各个程序。
shell脚本程序不是复杂的程序,它是按行解释的。脚本程序总以== #!/bin/sh ==开始,它通知shell使用系统上的Bourne shell解释器。
脚本程序是从上到下执行的,运行脚本程序前需要改变该脚本程序的执行权限。
Linux系统中有好多种不同的shell,但通常使用bash(bourne again shell)进行shell编程,因为bash是免费的并且很容易使用的。
常用shell操作
history 显示使用过的所有命令
!! 执行最近执行过的一条指令
!n 执行最近执行过的第n条指令
!string 执行最近一条以string开头的指令
!!:p 打印出最后一指令
!$ 用上条指令的最后一个参数做为当前指令的参数
可执行程序和内建命令的区别
大部分linux命令都有对应的…/bin,/sbin目录下的应用程序
内建命令不需要应用程序,即在默认路径下无法找到该命令
一个shell脚本的建立过程
首先终端建立一个文件
然后进入vi编辑器
按insert键,键入以下内容,再按ESC键,输入:wq退出保存
接着运行脚本
环境变量与shell变量
环境变量
每个shell都有一组预定义的环境变量,用户也可以自己指定环境变量.
HOME 主目录的完整路径
PATH shell搜索命令的路径
MAIL 邮箱的完整路径
USER 用户名
SHELL 登录shell的完整路径名
引用环境变量
$变量名
查看环境变量
env; set
指定局部变量为环境变量
export
例:export name
-
显示变量
-
消除变量
-
显示所有的本地shell变量
-
结合变量值
-
测试变量是否已经设置
-
使用变量来保存系统命令参数
-
设置只读变量
-
设置环境变量
-
显示环境变量
-
特定变量参数
系统预定义变量
变量 | 说明 |
---|---|
$$ | 当前shell的进程号 |
$# | 位置参数的数量 |
@ , @ , @,* | 所有位置参数的列表 |
$? | 命令执行后返回的状态 |
$! | 后台运行的最后一个进程号 |
$0 | 当前的shell脚本文件名 |
$RANDOM | 一个随机整数 |
$PPID | 父shell的进程ID |
$1…$9 | $n指向第n个命令行参数 |
Shell的输入输出
标准输入/输出
每个linux进程都会打开3个文件处理程序的输入/输出工作
文件 | 文件描述符 | 默认设备 |
---|---|---|
输入文件 | 0 | 键盘 |
输出文件 | 1 | 屏幕 |
错误输出文件 | 2 |
重定向
符号 | 说明 |
---|---|
> | 标准输出重定向到文件; |
>> | 标准输出追加到文件; |
< | 标准输入重定向到文件; |
<< | 标准输入追加到文件; |
输入重定向
语法:命令<输入文件
示例:$wc -l< inputfile
输出重定向
语法:命令>输出文件
示例:$ ls > outputfile
错误输出重定向
语法:命令 2>错误输出文件
示例:$make 2 >errorfile
管道
管道操作符 | ——特殊的重定向
语法:command1 |command2
前一个命令的输出作为后一个命令的输入
例:$who | wc -l 统计用户数
元字符
shell中赋予某些字符特殊的意义,称为元字符
输入命令时,shell扫描命令,对找到的元字符进行特殊处理,当处理完所有元字符时,命令最后执行
通配符
匹配零个或多个字符
举例:ls –l *.txt8
? 匹配任意单个字符
举例:ls –l ?.txt
[…] 匹配方括号之间的任何一个字符
举例:ls –l [123].txt
命令替换
` command` =$(command)
功能:替换为command的输出
举例:
$echo the date is `date`
the date is 五 2月 29 22:30:13 cts 2008
$ echo there are $(who | wc -l) users on the system
There are 6 users on the system
命令序列和组合命令
符号 | 用法 |
---|---|
; | 组成命令序列 |
(…) | 组合命令 |
举例:
$date;pwd;ls
$date>date.txt;ls;pwd>pwd.txt
$(date;ls;pwd)>out.txt
条件执行序列
||
功能:如果前一个命令执行失败,执行下一个命令
&&
功能:如果前一个命令执行成功,执行下一个命令
例:$gcc myprog.c && ./a.out
元字符—后台运行&
后台进程将在一个子shell中和父shell并发执行,不控制键盘
举例:
$./hello &
$kill –SIGINT 2654 (只能通过kill命令杀死hello进程)
元字符—注释#
元字符—引用变量的值$
举例:
$a=5
$echo $a
shell脚本
shell脚本的编辑和运行
- 建立、编辑脚本(vi,emacs,…)
- 运行脚本
1 . 修改脚本文件属性为可执行(chmod)->运行脚本(./ 脚本文件名)
(博客开始的位置创建脚本的实例就是用这种方法)
2 . $ source 脚本文件名
3 . $ . 脚本文件名(.和脚本直接有空格)
shell变量的特点
- shell变量使用之前不需要事先对它进行声明,在第一次使用它的时侯创建它。
- shell变量默认情况下,是字符串类型。
- shell变量名区分大小写。
- 弱类型。
局部变量引用
语法 | 说明 |
---|---|
${变量} | 变量值 |
${#变量} | 变量值的长度 |
${#变量} | 数组第1个元素的长度 |
${#变量[*]} | 数组元素的总个数 |
${变量:-word} | 如果变量存在且非null,返回它的值;否则返回word |
${变量:=word} | 如果变量存在且非null,返回它的值;否则将word赋值给变量,并返回变量的值 |
${变量:+word} | 如果变量存在且非null,返回word;否则返回null |
${变量:?word} | 如果变量存在且非null,返回它的值;否则显示“变量:word” |
${变量#pattern} | 匹配前缀(最小匹配),并返回余下内容 |
${变量##pattern} | 匹配前缀(最大匹配),并返回余下内容 |
${变量%pattern} | 匹配结尾(最小匹配),并返回余下内容 |
${变量%%pattern} | 匹配结尾(最大匹配),并返回余下内容 |
算术表达式
expr 外部命令
举例:
r=`expr 4 * 5`
echo $r
(此处注意前面“`”,然后在expr与4之间有空格,*需要转义,在“\*”的前后均有空格)
$(( ))
举例:
r=$((4*5))
echo $r
$[ ]
举例:
r=$[4*5]
echo $r
let
举例:
let r=4*5
echo $r
条件表达式
test命令
举例
$test $a –le $b
$echo $?
返回为0为真,为1为假
[ ]
举例
$[ $a –le $b ]
$echo $?
注意:使用[ ]测试条件时, [ ]要与测试条件之间留出空格。
数值测试
字符串测试
文件测试
语法 | 说明 |
---|---|
-a 文件名 | 如果文件存在则为真。 |
-e 文件名 | 如果文件存在则为真。 |
-r 文件名 | 如果文件存在且可读则为真。 |
-w 文件名 | 如果文件存在且可写则为真。 |
-x 文件名 | 如果文件存在且可执行则为真。 |
-s 文件名 | 如果文件存在且至少有一个字符则为真。 |
-d 文件名 | 如果文件存在且为目录则为真。 |
-f 文件名 | 如果文件存在且为普通文件则为真。 |
-c 文件名 | 如果文件存在且为字符型特殊文件则为真。 |
-b 文件名 | 如果文件存在且为块特殊文件则为真。 |
流程控制
if then else语句
语法
if 条件测试
then
条件为真时的命令串
else
条件为假时的命令串
fi
例子
#!/bin/bash
read answer
if (($answer==0))
then
echo “command was sucessful.”
else
if (($answer==-1))
then
echo “An error -1 was encountered.”
else
echo "An other error was encountered"
fi
fi
for循环
语法
for 变量名 [in数值列表]
do
若干个命令行
done
例子
#!/bin/bash
for i in 0 1 2 3 4 5 6 7 8 9
do
echo $i
done
while循环
语法
while 条件测试串
do
若干个命令行
done
例子
#!/bin/bash
x=0
while (($x<=10))
do
echo $x
x=$(($x+1))
done
until循环
语法
until 条件测试串
do
若干个命令行2
done
例子
#!/bin/bash
x=0
until (($x>10))
do
echo $x
x=$(($x+1))
done
shell还提供了true和false两条命令用于创建无限循环结构,它们的返回状态分别是总为0或总为1。
case条件
语法
case string in
exp-1)
若干个命令行1
;;
exp-2)
若干个命令行2
;;
……
*) #用*通配符来处理无匹配项情况
esac
例子
#!/bin/bash
echo “Enter A,B,C”
read letter
case $letter in
A|a) echo “you entered A;”
;;
B|b) echo “you entered B;”
;;
C|c) echo “you entered C”
;;
*) echo “not A,B,C”
esac
函数
函数定义
functionName()
{
命令序列;
}
函数调用
functionName
functionName 位置参数
例子
$cat func
#!/bin/bash
f()
{
echo ‘parameter $1=’$1
echo ‘parameter list=‘$*
}
#main program.
f 1
f cat my file1 file2
函数返回
return 用函数中执行的上一个命令的返回值返回;
return [value] 用给定的value值(0-255之间的整数)返回;
例子
#!/bin/bash
function fSum()
{
echo $1,$2;
return $(($1+$2));
}
fSum 5 7;
total=$(fSum 3 2);
echo $total,$?;
此处return只能返回上句话的运行结果,所以这个程序有错
全局函数
export命令可以将函数说明为全局函数,使其可以被子shell继承。
函数共享
把要共享的函数单独放在一个文件中,然后在要使用该函数的脚本中,在开始位置用以下格式的命令读取该文件。
. fileNme 或 source fileName
函数共享例子
函数定义脚本——libF.sh
#!/bin/bash
f()
{
echo “hello world”
}
函数调用脚本——main.sh
#!/bin/bash
. libF.sh
#此处也可以用source libF.sh
echo `f`
变量限制
local 变量名
限制变量只能本地shell的当前函数。
local声明例子
#!/bin/bash
sample_text="global variable"
foo() {
local sample_text="local variable"
echo "Function foo is executing"
echo $sample_text
}
echo "script starting"
echo $sample_text
foo
echo "script ended"
echo $sample_text