Shell编程入门教学文档Shell编程入门教学文档

来源:互联网 发布:手机调音器软件 编辑:程序博客网 时间:2024/04/29 05:15

Shell编程入门
一.Shell的自定义
shell是用户和Linux操作系统之间的接口。Linux中有多种shell,其中缺省使用的是Bash.
Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。
shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给Linux核心。
shell的另一个重要特性是它自身就是一个解释型的程序设计语言,shell程序设计语言支持绝大多数在高级语言中能见到的程序元素,如函数、变量、数组和程序控制结构。shell编程语言简单易学,任何在提示符中能键入的命令都能放到一个可执行的shell程序中。

二.Shell编程脚本流程
注意:在编写脚本时:
程序必须以下面的行开始(必须放在文件的第一行):
#!bin/sh
符号#!用来告诉系统后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。当编辑好脚本时,       如果要执行该脚本,还必须使用可执行。
要使脚本可执行:编译chmod +x filename 这样才能用 ./filename 来运行

三.shell基本语句
shell的基本语法主要就是如何输入命令运行程序以及如何在程序之间通过shell的一些参数提供便利手段来进行通讯。
具体的三种情况:
重定向
管道pipe
前台和后台
具体内容请参见(1-1.doc)。
四.Shell的变量
系统变量
用户变量
环境变量

<一>系统变量
Shell常用的系统变量并不多,但却十分有用,特别是做一些参数检测的时候。下面是Shell常用的系统变量 :

$n        $1 表示第一个参数,$2 表示第二个参数 ...
$#        命令行参数的个数
$0        当前程序的名称
$?        前一个命令或函数的返回码
$*        以“参数1 参数2 ... ” 形式保存所有参数
$@       以“参数1” “参数2” ... 形式保存所有参数
$$         本程序的(进程ID号)PID
$!          上一个命令的PID
其中使用得比较多得是 $n $# $0 $?
示例:请参见(1-2.doc)  

<二> shell用户变量
不管系统变量有多少,对于需求来说,总是不够的。用户变量是最常用到的变量,使用也十分简单。
用户定义的变量必须由字母数字及下划线组成,并且变量名的第一个字符不能为数字, 与其它UNIX名字一样,变量名是大小写敏感的. 对于用户变量,用户可按如下方式赋值:
name=“wanggou” 在引用变量时,需在前面加$符号,用户也可以在变量间进行相互赋值,如:
name="wanggou" 
wanggou=$name 
echo "Hello $wanggou !“
输出结果应该很清楚:Hello wanggou !
注意:这里需要注意一点:变量和'='之间不要有空格,'='和赋值也不要有空格,否则shell不会认为变量被定义。掌握了基本的使用方法,你可以完全开始你的编程工作了

<三>shell环境变量 
shell 环境变量是所有shell 程序都会接受的参数。shell程序运行时,都会接收一组变量,这组变量就是环境变量。常用的环境变量,请参见〈1-3.doc>.
这些变量,要关注的最多的就是PATH.
如何去定义新的环境变量:
定义新的环境变量,我们要用到export,看以下示例:
export MY_NAME=Wanggou
export PATH=/home/wanggou/bin:$PATH

<四>shell变量进行算术运算

五. shell语句
条件语句
     Shell程序中的条件语句主要有if语句、case语句;
循环语句
     shell常见的循环语句有for循环、while循环、until循环

<一>    test 测试命令
与传统的语言不同的是,shell用于指定条件值的不是布尔表达式而是命令和字符串。(在学习条件语句前,我们对test测试命令有个整体的 认识是必要的。)
test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
具体内容请参见(1-5.doc).

<二>循环语句之for循环
for循环
格式: for var in arg1 arg2 ... argn
do command
....
command
done
注意:var是变量名,arg1-n是数值列表。do到done之间是命令列表。
示例:请参见(1-6.doc)

<三>循环语句之while循环
while和until命令都是用命令的返回状态值来控制循环的
格式为

<四>循环语句之Until循环
<五>条件语句之if
<六>条件语句之case
语法:case 字符串 in 值1|值2) 操作:: 值3|值4) 操作:: 值5|值6) 操作:: *} 操作:: esac case的作用就是当字符串与某个值相同是就执行那个值后面的操作。如果同一个操作对于多个值,则使用”|”将各个值分开。在case的每一个操作的最后面都有两个”::”,分号是必须的。
    示例:请参见(1-10.doc).

<七>无条件控制语句
    break用于立即终止当前循环的执行,而contiune用于不执行循环中后面的语句而立即开始下一个循环的执行。这两个语句只有放在do和done之间才有效。
示例:请参见(1-11.doc)。

六.函数的定义
shell函数是一种为后续操作组织命令的方法,使用单个名字来命名这些命令组或者 routine。在shell或者是脚本当中,这个过程的名字必须是唯一的。所有用来组织函数的命令就像普通命令一样执行。当以一个简单的命令名来调用函数的时候,和该函数相关的命令就被执行。函数在必须声明,然后在shell里执行:没有新的进程会被创建来打断这个命令。
注意:特殊的内建命令在命令查找中先于shell函数。特殊的内建命令:break, :, ., continue, eval, exec, exit, export, readonly, return, set, shift, trap 和 unset.

七.函数的形式
函数使用以下2种形式。
function FUNCTION { COMMANDS; }
或者
FUNCTION () { COMMANDS; }
两者都定义了一个shell函数 FUNCTION
注意:内建的 function 命令是可选的;然而,如果不使用,必须在函数名后加上小括号。
八.函数中的位置参数
Shell函数:他们可以接受参数,他们可以使用只有在函数中有效的变量(使用本地内建 local )并且他们可以向调用者返回参数。
当函数开始执行,在执行期间函数的参数变成位置参数。扩展为位置参数的数量的特别参数 # 更新来反映这个变化。位置参数 0 未改变。Bash变量 FUNCNAME 在函数执行时被设置为函数的名字。
如果内建的 return 在函数中执行时,在调用完成后函数完成并且执行下一条命令。当函数完成后,位置参数的值和特别参数 # 被重置到函数执行前的值。如果一个数字参数被赋予 return ,那个状态就返回了。示例:请参见(1-13.doc)。

九.显示函数
所有被当前shell所识别的函数可以用 set 显示出来。函数在他们被使用后保留,除非使用后进行 unset 。

九.函数在脚本中的应用
<一>.循环利用
在你的系统中有大量的脚本使用函数来以结构化的方法处理一系列命令。在某些linux系统上,比如,你可以找到 /etc/rc.d/init.d/functions 定义文件,source在所有的初始化脚本中。使用这个方法通常只需要编写一次,常见的任务比如检查进程是否运行,开始或者停止一个守护进程等等。如果某些任务还需要一次,代码就可以重新循环使用。
示例:参见(1-14.doc)。
<二>.设置路径
<三>. 远程备分

参见实例如下

1-1.doc
(1)输入输出重定向
在shell中,使用者可以利用“>”和“<”来进行输入输出重定向。如:
     command>file:将命令的输出结果重定向到一个文件。

  command>&file:将命令的标准错误输出一起重定向到一个文件。

  command>>file:将标准输出的结果追加到文件中。

  command>>&file:将标准输出和标准错误输出的结果都追加到文件中。

command。< p="" />
(2)管道pipe
pipe同样可以在标准输入输出和标准错误输出间做代替工作,这样一来,可以将某一个程序的输出送到另一个程序的输入,其语法如下:
command1| command2[| command3...]
也可以连同标准错误输出一起送入管道:
command1| &command2[|& command3...]
(3)前台和后台
在shell下面,一个新产生的进程可以通过用命令后面的符号“;”和“&”来分别以前台和后台的方式来执行,语法如下:
command
产生一个前台的进程,下一个命令须等该命令运行结束后才能输入。
command &
产生一个后台的进程,此进程在后台运行的同时,可以输入其他的命令。
1-2.doc
#!/bin/bash
#This file is used to explain the shell system variable.
echo "the number of parameter is $# ";
echo "the return code of last command is $?";
echo "the script name is $0 ";
echo "the parameters are $* ";
echo "/$1 = $1 ; /$2 = $2 ";
1-4.doc
例如:
    $expr 2 + 1
     结果显示:3
    $expr 5 - 3
     结果显示:2若expr的一个参数是变量,那么在表达式计算之前用变量值替换变量名。
    $int=3
    $expr $int + 4
    结果显示:7
  用户不能单纯使用"*"做乘法,若输入:
    $expr 4*5
  系统将会报错,因为Shell看到"*"将会首先进行文件名替换。正确形式为:
    $expr 4 /* 5
     结果显示:20
  多个算术表达式可以组合在一起,例如:
    $expr 5 + 7 / 3
    结果显示:7
  运算次序是先乘除后加减,若要改变运算次序,必须使用"`"号,如:
    $int=`expr 5 + 7`
    $expr $int/3
     结果显示:4
    或者:
    $expr `expr 5+7` / 3
    结果显示:4
注意:红色的“$”是普通用户的意思。
1-5.doc
(1)数值测试:
       -eq:等于则为真
  -ne:不等于则为真
  -gt:大于则为真
  -ge:大于等于则为真
  -lt:小于则为真
  -le:小于等于则为真
(2)字符串测试:
  =:等于则为真
  !=:不相等则为真
  -z字符串:字符串长度伪则为真
  -n字符串:字符串长度不伪则为真
(3)文件测试:
  -e文件名:如果文件存在则为真
  -r文件名:如果文件存在且可读则为真
  -w文件名:如果文件存在且可写则为真
  -x文件名:如果文件存在且可执行则为真
  -s文件名:如果文件存在且至少有一个字符则为真
  -d文件名:如果文件存在且为目录则为真
  -f文件名:如果文件存在且为普通文件则为真
  -c文件名:如果文件存在且为字符型特殊文件则为真
-b文件名:如果文件存在且为块特殊文件则为真
注意:另外,Linux还提供了与(“!”)、或(“-o)、非(“-a”)三个逻辑操作符用于将测试条件连接起来,其优先级为:“!”最高,“-a”次之,“-o”最低。
1-6.doc
#!/bin/bash
for wangluo in wanggou wangguan
do
echo $wangluo
done
1-7.doc
示例:用“while”计算1到5的平方
#!/bin/bash
int=1
while [ $int -le 5 ]
do
sq=`expr $int //* $int`
echo $sq
int=`expr $int + 1`
done
echo "恭喜成功,接着来看写一个。"
1-8.doc
示例:使用until结构计算1-5的平方
#!/bin/bash

int=1

until [ $int -gt 5 ]
do
sq=`expr $int //* $int`
echo $sq
int=`expr $int + 1`
done
echo "成功了,恭喜你!!继续努力呀。"
1-9.doc
#!/bin/bash
if   [ "$SHELL" = "/bin/sh" ]; then
 echo "your login shell is the sh "
else
 echo "your login shell is not bash but $SHELL"
fi
1-10.doc
#!/bin/bash
case $USER in
beichen)
Echo “You are beichen!”;;
liangnian)
echo “You are liangnian”; //注意这里只有一个分号
echo “Welcome!”;; //这里才是两个分号
root)
echo “You are root!:echo Welcome!”;; //将两命令写在一行,用一个分号作为分隔符
*)
echo “Who are you?$USER?”;;
esac
输出的结果是:
You are root!
Welcome!
1-11.doc
#!/bin/bash
echo "What is your favourite OS?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
    break
done
echo "You have selected $var"

注意:break要放在do和done之间才有效.
1-12.doc
#!/bin/bash 
function func() { 
 echo $1 
 echo $2 
 return 1 
} 
func "Hello" "What is your name?"
1-13.doc
#vi jiaoben
#!/bin/bash                                                                        echo "This script demonstrates function arguments."
echo                                                                             
echo "Positional parameter 1 for the script is $1."
echo                                                                             
test ()
{
echo "Positional parameter 1 in the function is $1."
RETURN_VALUE=$?
echo "The exit code of this function is $RETURN_VALUE."
}                                                                              test other_param
退出保存
chmod a+x jiaoben   #赋予可执行权限
./jiaoben understand?      #执行jiaoben
1-14.doc
# Check if $pid (could be plural) are running
checkpid() {
         local i

         for i in $* ; do
                 [ -d "/proc/$i" ] && return 0
         done
         return 1
}
注意:这个函数在相同的脚本中在重用于其他脚本的其他函数中被重用。 守护进程 ,比如,多数使用在启动一个服务进程的起始脚本中
1-15.doc
pathmunge () {
         if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
            if [ "$2" = "after" ] ; then
               PATH=$PATH:$1
            else
               PATH=$1:$PATH
            fi
         fi
}

# Path manipulation
if [ `id -u` = 0 ]; then
         pathmunge /sbin
         pathmunge /usr/sbin
         pathmunge /usr/local/sbin
fi

pathmunge /usr/X11R6/bin after

unset pathmunge
注释:这个函数把第一个参数设置为路径名。如果路径名不在当前路径中,就把它加入。传给函数的第二个参数定义了路径是加入到当前 PATH 之前还是之后。
普通用户只把 /usr/X11R6/bin 加入到他们的路径中,当 root 得到了一些包含系统命令的额外目录。使用完毕后,函数就进行unset所以就不存在了。
1-16.doc
在星期天,只有 bupbash 运行。
#/bin/bash

LOGFILE="/nethome/tille/log/backupscript.log"
echo "Starting backups for `date`" >> "$LOGFILE"

buplinux()
{
DIR="/nethome/tille/xml/db/linux-basics/"
TAR="Linux.tar"
BZIP="$TAR.bz2"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"

cd "$DIR"
tar cf "$TAR" src/*.xml src/images/*.png src/images/*.eps
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
echo -e "Done backing up Linux course:/nSource files, PNG and EPS images./nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}

bupbash()
{
DIR="/nethome/tille/xml/db/"
TAR="Bash.tar"
BZIP="$TAR.bz2"
FILES="bash-programming/"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"

cd "$DIR"
tar cf "$TAR" "$FILES"
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"

echo -e "Done backing up Bash course:/n$FILES/nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}

DAY=`date +%w`

if [ "$DAY" -lt "2" ]; then
   echo "It is `date +%A`, only backing up Bash course." >> "$LOGFILE"
   bupbash
else
   buplinux
   bupbash
fi


echo -e "Remote backup `date` SUCCESS/n----------" >> "$LOGFILE"


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/SmartTony/archive/2008/01/22/2060104.aspx

原创粉丝点击