shell编程
第一个shell脚本
使用vim编辑first.sh
$ vim first.sh
编辑first.sh
clear echo "Hello $USER" echo "Today is \c ";date echo "Number of user login : \c" ; who | wc -l echo "Calendar" cal exit 0
执行时,需要
$ chmod 755 frist.sh $ ./first.sh
或者是
$ sh first.sh
系统变量
系统变量名称 | 变量名的意义 |
BASH=/bin/bash | shell名 |
BASH_VERSION=1.14.7(1) | shell版本名 |
COLUMNS=80 | 屏幕中的第几列 |
HOME=/home/vivek | home目录 |
LINES=25 | 屏幕中的第几列 |
LOGNAME=students | 当前的登录名 |
OSTYPE=Linux | 操作系统名 |
PATH=/usr/bin:/sbin:/bin:/usr/sbin | PATH的设置 |
PS1=[\u@\h \W]\$ | 提示设置 |
PWD=/home/students/Common | 当前工作目录 |
SHELL=/bin/bash | shell名 |
USERNAME=vivek | 当前登录的用户名 |
使用echo命令查看环境变量,如
$ echo $HOME
变量的定义
定义的格式如下:
variable name=value
例如
$ no=10 $ echo $no
注意变量名是区分大小写的
no 与 No 不是一个变量
定义一个NULL变量, 可以如下
$ vech= $ vech=""
介绍一下echo命令的选项
echo [options] [string, variables...]
其中options可以为
-n 不作为一行输出,即输出后不换行
-e 将下面的反斜杠解释成转义字符:
\a 警报
\b 删除
\c 不换行
\n 新建一行
\r 回车键
\t 水平tab
\\ 反斜杠
$ echo -e "An apple a day keeps away \a\t\tdoctor\n"
打印彩色字符串
$ echo -e "\033[34m Hello Colorful World!"
1) 第一个\033是换码符
2) 用[34m设置屏幕的前背景是蓝色
character or letter |
use in CSI |
例子 |
h | 设置ANSI模式 | echo -e "\033[h" |
l | 清除ANSI模式 | echo -e "\033[l" |
m | 设置输出字的颜色以及是否粗体 | echo -e "\033[35m Hello World" |
q | 设置num lock,caps lock,scroll lock开还是关 | echo -e "\033[2q" |
s | 存储当前光标的x,y坐标还有属性 | echo -e "\033[7s" |
u | 重新存储当前光标的x,y坐标还有属性 | echo -e "\033[8u" |
其中m参数的意义如下
参数 | 意义 | 例子 |
0 | 设置默认的颜色模式 | |
1 | 设置粗体强度 | $ echo -e "I am \033[1m BOLD \033[0m Person" |
2 | 设置暗淡强度 | $ echo -e "\033[1m BOLD \033[2m DIM \033[0m" |
5 | 设置闪烁强度 | $ echo -e "\033[5m Flash! \033[0m" |
7 | 设置相反的效果 | $ echo -e "\033[7m Linux OS! Best OS!! \033[0m" |
11 |
显示特殊控制字符图形字符。 对于如从按下Alt键和数字键盘按178发, 放开两个键;没有将被打印。 试一下示例中的输出 |
$ press alt + 178 $ echo -e "\033[11m" |
25 | 删除闪烁效果 | |
27 | 删除相反效果 | |
30 - 37 |
设置前景颜色: 31 - 红色 32 - 绿色 xx - 自己试一下
|
$ echo -e "\033[31m I am in Red" |
40 - 47 |
设置背景颜色 xx - 自己试一下 |
$ echo -e "\033[44m Wow!!!" |
q参数的意义如下
参数 | 意义 |
0 | 关掉所有键盘的LED灯 |
1 | Scroll lock LED 打开,其他的关掉 |
2 | Num lock LED 打开,其他的关掉 |
3 | Caps lock LED 打开,其他的关掉 |
算术运算
算术运算的格式如下:
expr op1 math-operator op2
示例:
$ expr 1 + 3 $ expr 2 - 1 $ expr 10 / 2 $ expr 20 % 3 $ expr 10 \* 3 $ echo `expr 6 + 3`
注意乘法使用 \* 而不是 *
注意最后一个示例不是单引号,是ESC键下面的键的符号
用双引号或单引号只是打印字符串, 如下
$ echo "expr 6 + 3" $ echo 'expr 6 + 3'
双引号: 在双引号里面的内容会将特殊字符替换
单引号: 在单引号里面的内容不会变,直接打印
反引号(即ESC键下面的键):里面的内容作为命令执行之后替换
如下:
$ echo "Today is date" $ echo 'Today is date' $ echo "Today is `date`" $ echo 'Today is `date`'
命令退出状态
1) 如果返回值是0, 则说明命令执行成功
2) 如果返回值不是0, 则说明命令没有执行成功,或者是脚本中一些命令没有执行成功
使用 $?
用echo $?查看上一条命令的执行状态
$ ls $ echo $?
读取变量
读取变量名的格式如下:
read variable1, variable2,...variableN
编辑sayH文件
echo "Your first name please:" read fname echo "Hello $fname, Lets be friend!"
下面执行
$ chmod 755 sayH $ ./sayH
如果一行使用多个命令,命令之间使用;隔开
$ date;who
如果一个脚本有参数,在脚本内 $0 是脚本名,$1 是第一个参数, $2 是第二个参数,$# 是传递的参数个数, $@ 或 $* 是所有的参数
编辑demo文件
#!/bin/sh # # Script that demos, command line args # echo "Total number of command line argument are $#" echo "$0 is script name" echo "$1 is first argument" echo "$2 is second argument" echo "All of them are :- $* or $@"
执行
$ chmod 755 demo $ ./demo Hello World
管道
使用格式如下
command1 | command2
$ who | wc -l
第一条命令的输出结果作为第二条命令的输入
bc是计算命令
$bc 5 + 2 5 > 12 5 == 10 5 != 2 5 == 5 12 < 2
表达式 | 含义 | 答案 | bc的结果 |
5 > 12 | 5是否大于12 | NO | 0 |
5 == 10 | 5是否等于10 | NO | 0 |
5 != 2 | 5是否不等于2 | YES | 1 |
5 == 5 | 5是否等于5 | YES | 1 |
12 < 2 | 12是否小雨2 | NO | 0 |
if条件语句
使用格式如下
if condition
then
command1 if condition is true or if exit status
of condition is 0 (zero)
...
...
fi
编辑showfile文件
#!/bin/sh # #Script to print file # if cat $1 then echo -e "\n\nFile $1, found and successfully echoed" fi
执行
$ chmod 755 showfile $./showfile foo
编辑ispostive文件
#!/bin/sh # # Script to see whether argument is positive # if test $1 -gt 0 then echo "$1 number is positive" fi
执行
$ chmod 755 ispostive $ ispostive 5
判断条件
test 或者 [expr] 作用于整数,文件类型,字符串
数学符号 | 含义 | 一般表达式 | shell中的test | shell中的[expr] |
-eq | 等于 | 5 == 6 | if test 5 -eq 6 | if [ 5 -eq 6 ] |
-ne | 不等于 | 5 != 6 | if test 5 -nq 6 | if [ 5 -nq 6 ] |
-lt | 小于 | 5 < 6 | it test 5 -lt 6 | if [ 5 -lt 6 ] |
-le | 小于或等于 | 5 <= 6 | if test 5 -le 6 | if [ 6 -le 6 ] |
-gt | 大于 | 5 > 6 | it test 5 -gt 6 | if [5 -gt 6 ] |
-ge | 大于或等于 | 5 >= 6 | if test 5 -ge 6 | if [ 5 -ge 6] |
对字符串的比较
操作符 | 含义 |
string1 = string2 |
string1 是否等于string2 |
string1 != string2 | string1 是否不等于 string2 |
string1 | string1 不为 NULL 或 不是没定义 |
-n string1 | string1 不为NULL 并且存在 |
-z string1 | string1 为NULL 并且存在 |
对于文件或者是目录
test | 含义 |
-s file | 不为空文件 |
-f file | 文件是否存在或是普通文件并且不是目录 |
-d dir | 目录是否存在且不是一个普通文件 |
-w file | 文件是否可写 |
-r file | 文件是否可读 |
-x file | 文件是否可执行 |
逻辑运算
运算符 | 含义 |
! expression | 逻辑非 |
expression1 -a expression2 | 逻辑与 |
expression1 -o expression2 | 逻辑或 |
条件语句 if - else - fi
使用格式如下
if condition
then
condition is zero (true - 0)
execute all commands up to else statement
else
if condition is not true then
execute all commands up to fi
fi
编辑isnump_n文件
#!/bin/sh # # Script to see whether argument is positive or negative # if [ $# -eq 0 ] then echo "$0 : You must give/supply one integers" exit 1 fi if test $1 -gt 0 then echo "$1 number is positive" else echo "$1 number is negative" fi
执行
$ chmod 755 isnump_n $ isnump_n 5 $ isnump_n -45 $ isnump_n $ isnump_n 0
嵌套if - else - fi
使用格式如下
if condition then if condition then ..... .. do this else .... .. do this fi else ... ..... do this fi
编辑nestedif.sh
osch=0 echo "1. Unix (Sun Os)" echo "2. Linux (Red Hat)" echo -n "Select your os choice [1 or 2]? " read osch if [ $osch -eq 1 ] ; then echo "You Pick up Unix (Sun Os)" else #### nested if i.e. if within if ###### if [ $osch -eq 2 ] ; then echo "You Pick up Linux (Red Hat)" else echo "What you don't like Unix/Linux OS." fi fi
执行
$ chmod +x nestedif.sh $ ./nestedif.sh $ ./nestedif.sh $ ./nestedif.sh
多层if - else - fi
if condition
then
condition is zero (true - 0)
execute all commands up to elif statement
elif condition1
then
condition1 is zero (true - 0)
execute all commands up to elif statement
elif condition2
then
condition2 is zero (true - 0)
execute all commands up to elif statement
else
None of the above condtion,condtion1,condtion2 are true (i.e.
all of the above nonzero or false)
execute all commands up to fi
fi
编辑elf
# #!/bin/sh # Script to test if..elif...else # if [ $1 -gt 0 ]; then echo "$1 is positive" elif [ $1 -lt 0 ] then echo "$1 is negative" elif [ $1 -eq 0 ] then echo "$1 is zero" else echo "Opps! $1 is not number, give number" fi
执行
$ chmod 755 elf $ ./elf 1 $ ./elf -2 $ ./elf 0 $ ./elf a
shell中的循环
for 循环
格式如下:
for { variable name } in { list }
do
execute one for each item in the list until the list is
not finished (And repeat all statement between do and done)
done
编辑testfor文件
for i in 1 2 3 4 5 do echo "Welcome $i times" done
执行
$ chmod +x testfor $ ./testfor
编辑mtable文件
#!/bin/sh # #Script to test for loop # # if [ $# -eq 0 ] then echo "Error - Number missing form command line argument" echo "Syntax : $0 number" echo "Use to print multiplication table for given number" exit 1 fi n=$1 for i in 1 2 3 4 5 6 7 8 9 10 do echo "$n * $i = `expr $i \* $n`" done
执行
$ chmod 755 mtable $ ./mtable 7 $ ./mtable
另一种格式如下
for (( expr1; expr2; expr3 ))
do
.....
...
repeat all statements between do and
done until expr2 is TRUE
Done
编辑for2文件
for (( i = 0 ; i <= 5; i++ )) do echo "Welcome $i times" done
执行
$ chmod +x for2 $ ./for2
嵌套for循环
编辑nestedfor文件
for (( i = 1; i <= 5; i++ )) ### Outer for loop ### do for (( j = 1 ; j <= 5; j++ )) ### Inner for loop ### do echo -n "$i " done echo "" #### print the new line ### done
执行
$ chmod +x nestedfor.sh $ ./nestefor.sh
编辑chessboard文件
for (( i = 1; i <= 9; i++ )) ### Outer for loop ### do for (( j = 1 ; j <= 9; j++ )) ### Inner for loop ### do tot=`expr $i + $j` tmp=`expr $tot % 2` if [ $tmp -eq 0 ]; then echo -e -n "\033[47m " else echo -e -n "\033[40m " fi done echo -e -n "\033[40m" #### set back background colour to black echo "" #### print the new line ### done
执行
$ chmod +x chessboard $ ./chessboard
while循环
使用格式如下
while [ condition ]
do
command1
command2
command3
..
....
done
编辑nt1文件
#!/bin/sh # #Script to test while statement # # if [ $# -eq 0 ] then echo "Error - Number missing form command line argument" echo "Syntax : $0 number" echo " Use to print multiplication table for given number" exit 1 fi n=$1 i=1 while [ $i -le 10 ] do echo "$n * $i = `expr $i \* $n`" i=`expr $i + 1` done
执行
$ chmod 755 nt1 $./nt1 7
case语句
使用格式如下
case $variable-name in
pattern1) command
...
..
command;;
pattern2) command
...
..
command;;
patternN) command
...
..
command;;
*) command
...
..
command;;
esac
编辑car文件
# # if no vehicle name is given # i.e. -z $1 is defined and it is NULL # # if no command line arg if [ -z $1 ] then rental="*** Unknown vehicle ***" elif [ -n $1 ] then # otherwise make first arg as rental rental=$1 fi case $rental in "car") echo "For $rental Rs.20 per k/m";; "van") echo "For $rental Rs.10 per k/m";; "jeep") echo "For $rental Rs.5 per k/m";; "bicycle") echo "For $rental 20 paisa per k/m";; *) echo "Sorry, I can not gat a $rental for you";; esac
执行
$ chmod +x car $ car van $ car car $ car Maruti-800
如何de-bug shell脚本
使用格式
sh options {shell 脚本名}
或者是
bash options {shell 脚本名}
options可以是
-v 当shell读脚本时把脚本内容打印出来
-x 脚本中的命令会展开打印出来
编辑dsh1文件
# # Script to show debug of shell # tot=`expr $1 + $2` echo $tot
执行
$ chmod 755 dsh1.sh $ ./dsh1.sh 4 5 $ sh -x dsh1.sh 4 5 $ sh -v dsh1.sh 4 5
第一个输出结果
9
第二个输出结果
+ expr 4 + 5
+ tot=9
+ echo 9
9
第三个输出结果
#
#script to show debug of shell
#
tot=`expr $1 + $2`
echo $tot
9