shell编程入门

Shell 背景

第一个重要的 shell 是 Bourne shell (如此命名是为了纪念此 shell 的发明者 Steven Bourne), 1979 年第一个流行的 Unix 版本 7 发行时, 开始使用

Bourne shell. Bourne shell 的主档名为 sh, 因此, 日后人们便以 sh 为 Bourne shell 的主要识别名称. 虽然目前Unix 上的 shell 有许多种, 但 Bourne shell

的地位至今仍然没有改变. 许多 Unix 系统中仍然使用 sh 做为重要的管理工具.

第一个广为流行使用的 shell 变种是 C shell. C shell 主要附在 BSD 版的 Unix 系统中. 它的作者是柏克利大学的 Bill Joy. C shell 主要是因为其语法和 C 语言

相类似,因而得名. 这使得 Unix 系统的程式师, 在学习 C shell 时, 感到相当地方便容易. 以上这二种形成 shell 的二大主流, 后来的变种 shell 大都攫取这二种 shell 的优点.

比如 Korn, tcsh 及 bash.

Bash shell 是 GNU 计划的重要工具软体之一, 也是 GNU 作业系统中标准的 shell.Bash 相容于 sh, 因此, 许多早期开发出来的 Bourne shell 都可以继续在 bash

中运作. 现在我们安装好的 Redhat Linux 便是完全使用 Bash. (/bin/sh -> /bin/bash)


什么是Shell

在计算机科学中,Shell俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。它类似于DOS下的command和后来的cmd.exe。它接收用户命令,

然后调用相应的应用程序。同时它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计

语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

基本上shell分两大类:

一:图形界面shell(Graphical User Interface shell 即 GUI shell)

二:命令行式shell(Command Line Interface shell ,即CLI shell)

常用的Shell命令有:
cat 文件名 输出文件内容到基本输出(屏幕 or 加>fileName 到另一个文件)
cb 格式化源代码
chmod //change mode,改变文件的权限
cp copy
date 当前的时间和日期
echo $abc 在变量赋值之后,只需在变量前面加一个$去引用.
lint 语法检查程序
ls dir
man help
more type
du 查看磁盘空间状况
ps 查看当前进程状况
who 你的用户名和终端类型
定义变量 name=abc? (bash/pdksh) || set name = abc (tcsh)
mkdir 创建目录
rmdir 删除目录
cd 进入目录
rm 删除文件
more 显示文件
echo 显示指定文本
mv 改文件名
pwd 显示目录路径命令

Shell程序的基本结构:

使用编辑器创建一个hello.sh,内容如下:

#! /bin/bash
#hello
echo 'hello world'

这里需要说明的:
1.养成良好的习惯,shell文件以".sh"作为后缀(不用.sh为后缀的文件也可以运行)
2.注释使用"#"开头
3.文本的第一行一定要写成 #!/bin/bash (#!后是你使用shell所在的路径)
4.编辑的文本要想让其运行,在终端中使用“chmod +x hello.sh”命令(添加可执行权限)
5.运行程序:在终端中使用“ ./hello.sh”命令


Shell中的三种变量:系统变量,环境变量,用户自定义变量

用户自定义变量:编程中用户声明的变量,这里不做说明

系统变量:
常用的系统变量有:

$0 当前程序的名称
$n 当前程序的第n个参数,n=1,2,…9
$* 当前程序的所有参数(不包括程序本身)
$# 当前程序的参数个数(不包括程序本身)
$$ 当前程序的PID
$@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
$- 显示shell使用的当前选项,与set命令功能相同
$! 执行上一个指令的PID(好像不行?)
$? 执行上一个指令的返回值

环境变量:
shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量

在终端中使用“export”命令可以查看系统的环境变量列表

1. 常见的环境变量。
PATH: 系统路径.
HOME: 当前用户家目录
HISTSIZE: 保存历史命令记录的条数。
LOGNAME: 当前用户登录名。
HOATNAME: 主机名称,若应用程序要用到主机名的话,一般是从这个环境变量中的取得的.
SHELL: 当前用户用的是哪种shell.
LANG/LANGUGE: 和语言相关的环境变量,使用多种语言的用户可以修改此环境变量.
MAIL: 当前用户的邮件存放目录.

2. 设置环境变量的方法
etho:显示指定环境变量。
export:设置新的环境变量
env:显示所有环境变量。
set:显示所有本地定义的shell变量。
unset:清除环境变量。

3.几个实例
①. 显示环境变量HOME
$ echo $HOME
/home/leon

②设置一个新的环境变量hello
$ export HELLO="Hello!"
$ echo $HELLO
Hello!

③使用env命令显示所有的环境变量
$ env
HOSTNAME=redbooks.safe.org
PVM_RSH=/usr/bin/rsh
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
  ...

④ 使用set命令显示所有本地定义的Shell变量
  $ set
  BASH=/bin/bash
  BASH_VERSINFO=([0]="2"[1]="05b"[2]="0"[3]="1"[4]="release"[5]="i386-redhat-linux-gnu")
  BASH_VERSION='2.05b.0(1)-release'
  COLORS=/etc/DIR_COLORS.xterm
  COLUMNS=80
  DIRSTACK=()
  DISPLAY=:0.0
   ...

⑤使用unset命令来清除环境变量
set可以设置某个环境变量的值。清除环境变量的值用unset命令。如果未指定值,则该变量值将被设为NULL。示例如下:
$ export TEST="Test..." #增加一个环境变量TEST
$ env|grep TEST #此命令有输入,证明环境变量TEST已经存在了
TEST=Test...
$ unset $TEST #删除环境变量TEST
$ env|grep TEST #此命令没有输出,证明环境变量TEST已经存在了

⑥ . 使用readonly命令设置只读变量
如果使用了readonly命令的话,变量就不可以被修改或清除了。示例如下:
$ export TEST="Test..." #增加一个环境变量TEST
$ readonly TEST #将环境变量TEST设为只读
$ unset TEST #会发现此变量不能被删除
-bash: unset: TEST: cannot unset: readonly variable
$ TEST="New" #会发现此也变量不能被修改
-bash: TEST: readonly variable
环境变量的设置位于/etc/profile文件
如果需要增加新的环境变量可以添加下属行
export path=$path:/path1:/path2:/pahtN

在实例②中是使用export命令来定义一个环境变量,这样的环境变量只在当前运行的所有进程中有效,并没有保存到系统的文件中。系统重启后就没法再访问这些变量,

因此,可以再系统配置中配置这些环境变量。环境变量的系统配置文件是/etc/profile。配置环境变量步骤如下:

1.在终端中使用“gedit /etc/profile”命令(编辑profile文件)

2.在文件最后添加如下代码,添加两个环境变量
export A1=hello
export A2=123
3.保存该文件,重启计算机后,系统中会产生上面设置的两个环境变量


Shell的运算符

= str=hello
+ 加
- 减
* 乘
/ 除
** 幂运算
% 取模运算(求余)
+= 加等于(在自身基础上加上第二个变量)
-= 减等于
*= 乘等于
/= 除等于
%= 去摸赋值(第一个变量对第二个变量取模运算,在赋值给第一个变量)

问题:echo 1+2
Shell并没有输出结果3,而是输出1+2

解决办法:用三种方法分别更改运算顺序
①用expr改变运算顺序:使用echo `expr 1+2`输出“1+2”,注意“`”不是单引号,是“Tab”键上面的那个符号

②用let指示数学运算:先将运算结果赋值给b,运算命令是b=let 1+2,然后用echo $b来输出,如果没有let还是会输出1+2

③用$[]表示数学运算:使用echo $[1+2],输出结果3

使用位置变量实现运算:

编辑operation.sh文件,内容如下:
#!/bin/bash
#operation.sh
s=0
s=`expr $1**S2`
echo $s

在终端中使用“chmod +x operation.sh”对该文件附加执行权限后,使用“./operation.sh 2 4”命令,则运算的输出结果是16(2的4次方)。

说明:位置变量是值Shell程序在运行时传入的参数。程序中可以用变量的形式调用这些参数。这些参数被存放到1~9($0,$1……$9)的九个变量名中,被形象称为位置变量。


输入和输出

使用read命令输入:
1. “read A”相当于C语言中的scanf()函数
2. 也可以“read A B”输入多个值,分别赋值给A和B

使用echo输出:
1. echo $str #将结果输出到终端
2. echo $str >file #将结果输出到file文件,如果没有该文件则会新建一个文件,并覆盖该文件内容
3. echo $str >>file #将结果追加到file文件中
4. 格式控制字符\c、\t和\n的使用:
\c:不换行
\t:跳格,相当于“Tab”键
\n:换行
注意:使用格式控制字符时,必须加-e选项,如echo -e "hello\tBeijing",则输出“hello Beijing”

5. Shell中的转义字符是反斜杠“\”


Shell测试语句的使用

文件状态测试:

文件状态测试是指对文件的权限、有无、属性、类型等内容进行判断。与其他语言不同的是,test命令的测试结果,返回0表示测试成功。返回1表示测试失败。

主要参数有
-d 测试是否为目录
-f 测试是否为文件
-e 测试目录或文件是否存在
-r 测试当前用户是否有读取权
-w 测试当前用户是否有写入权限
-x 测试当前用户是否有执行权限
实例:
1. 测试文件是否是一个目录:test -d /file
2. 测试当前目录下的文件a.txt是否可执行:test -x a.txt


数值测试:

是指比较两个数值的大小或相等关系

语法:test 第一个操作数 数值比较符 第二个操作数
或者:[ 第一个操作数 数值比较符 第二个操作数 ]
注意:[ ]间与操作数间有一个间隔

数值比较符有:
-eq 相等
-ne 不相同
-le 小于等于
-ge 大于等于
-gt 大于
-lt 小于

实例:
1.测试3和5是否相等:test 3 -eq 5 或者 [ 3 -eq 5 ]
2.测试10是否小于12:test 10 -lt 12 或者 [ 10 -lt 12 ]


字符串测试:

指比较两个字符串是否相等,或者判断一个字符串是否为空,这种判断常用来测试用户输入是否符合程序要求。

常用方法:
test 字符串比较符 字符串
test 字符串1 字符串比较符 字符串2
[ 字符串比较符 字符串1 ]
[ 字符串1 字符串比较符 字符串2 ]

字符串比较符:
= 第一个字符串和第二个字符串相等
!= 第一个字符串和第二个字符串不相等
-z 检查字符串是否为空
-n 检查字符串是否为非空

实例:测试变量A与变量B是否相等:test $A = $B

逻辑测试:

-a 逻辑与
-o 逻辑或
! 逻辑否

实例:测试文件a.txt是否为可写可执行:[ -w a.txt -a -x .txt ]


流程控制结构:

if语句:
编辑一个test.sh文件,内容如下:

#!/bin/sh
echo "Is it morning? Please answer yes or no"
read time
if [ "$time" = "yes" ]; then echo "Good morning"
elif [ "$time" = "no" ]; then echo "Good afternoon"
else echo "Sorry,$time not recquired,Enter yes or no"
exit 1
fi
exit 0

说明:if结构必须要用fi进行结束;
elif相当于else if 不是语法错误

for语句:

语法:
for 变量名 in 列表
do
命令1
命令2……
done

实例1:
#!/bin/sh
for foo in 1 2 3
do
echo $foo
done
exit 0

输出: 1
2
3

实例2:
#!/bin/sh
for str
do
echo -e "$str\c"
done

当for语句省略in关键字是,将接受输入命令的参数作为循环变量集,在终端中输入test.sh a b c,程序输入结果为:abc

实例3:
使用通配符扩展的for循环
for循环经常与Shell对文件名的通配符扩展一起使用.即在字符串的值里加上个通配符,由Shell在程序执行时填充所有的值. 例如

#!/bin/sh
for file in $(ls *.sh);
do
lpr $file
done
exit 0

这个例子把当前目录里的.sh的文件都打印出来.

实例4:
九九乘法表
#!/bin/sh
for i in 1 2 3 4 5 6 7 8 9
do
for j in 1 2 3 45 6 7 8 9
do
if [ $j -le $i] #比较i和j的大小关系实现排列
then echo -e "$j\c"
echo -e "*\c"
echo -e "$i\c"
echo -e "=\c"
echo -e "$[ $i*$j ] \c"
fi
done
echo ""
done


while语句:

实例
#!/bin/sh
foo=1
while [ $foo -le 3 ]
do
echo "Now foo is $foo"
foo=$(($foo+1))
done

输出: Now foo is 1
Now foo is 2
Now foo is 3

until语句:

语法:
until 条件
do
命令1
……
done

实例

#!/bin/sh
i=1
until [ $i -gt 3 ]
do
echo -e "$i\c"
i=$[$i+1]
done

输出结果为:123

posted @ 2015-10-09 11:54  一天一夜  阅读(249)  评论(0编辑  收藏  举报