Shell编程入门

  • shell语法
  • shell变量
  • shell变量表达式
  • shell条件判断语句if、case
  • shell循环控制语句for、while、until
shell语法
  • 开头
  • 注释
  • 执行命令 例如:使用vi编辑器创建/root/date文件,如下共有三行命令
  1. 创建文件
[root@localhost ~]# vi /root/date

#!/bin/bash
#filename:date
echo "Mr.$USER,Today is:"
echo $(date)
echo Whish you a lucky day !

2.设置可执行权限

[root@localhost ~]# chmod u+x /root/date

使用ls命令可以查看/root/date文件具有可执行权限

[root@localhost ~]# ls -l /root/date
-rwxr--r--. 1 root root 95 Jul 18 18:25 /root/date

3.输入这个文件的完整路径即可执行Shell程序

[root@localhost ~]# /root/date
Mr.root,Today is:
Thu Jul 18 18:37:48 EDT 2019
Whish you a lucky day !

4.使用bash命令执行程序(当使用bash执行程序时,就是告诉系统它是一个可执行脚本,不需要设置/root/date的可执行权限也可以执行)

[root@localhost ~]# chmod u-x /root/date  
[root@localhost ~]# ls -l /root/date
-rw-r--r--. 1 root root 95 Jul 18 18:25 /root/date
[root@localhost ~]# /root/date
-bash: /root/date: Permission denied
[root@localhost ~]# bash /root/date
Mr.root,Today is:
Thu Jul 18 18:44:42 EDT 2019
Whish you a lucky day !

Shell变量

1.常用环境变量

Shell环境变量描述
HOME 用于保存用户主目录的完全路径名
PATH 用于保存用冒号分割的目录路径名,Shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。
TERM 终端的类型
UID 当前用户的UID,由数字构成
PWD 当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化
PS1 主提示符,在root用户下,默认得住提示符是“#”,在普通用户下,默认的主提示符是“$”
PS2 在Shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“”然后按回车键,或者当用户按回车键时Shell判断出用户输入的命令没有结束时,就显示这个辅助提示符,提示用户继续输入命令的其余部分,默认的辅助提示符是“>”

例如:查看当前用户Shell定义的环境变量的值

[root@localhost ~]# echo $HOME
/root
[root@localhost ~]# echo $PWD
/root
[root@localhost ~]# echo $PS1
[u@h W]$
[root@localhost ~]# echo $PS2
>
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# echo $TERM
xterm
[root@localhost ~]# echo $UID
0

2.定义用户的变量 语法:变量名=变量值

注意:定义变量时,变量名前不应该家符合“$”,在引用变量的内容时则应在变量名前加符合“$”.在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来。在编写Shell程序时,为了使变量名和命令名相区别,建议所有的变量名都用大写字母来表示。

例如:变量值中包含了空格,需将整个字符串用双引号括起来

[root@localhost ~]# AA="Hello Linux"
[root@localhost ~]# echo $AA
Hello Linux
  • readonly 变量名

在说明一个保留并将它设置为一个特定值后就不再改变它的值时,可以使用readonly命令来保证一个变量的只读性。

例如:设置变量A为只读

[root@localhost ~]# A=100
[root@localhost ~]# readonly A
[root@localhost ~]# echo $A
100
[root@localhost ~]# A=200
-bash: A: readonly variable
  • export 变量名

在任何时候创建的变量都只是当前Shell的局部变量,所有不能被Shell运行的其他命令或 Shell程序所利用,而export命令可以将一个局部变量提供给Shell命令使用。

例如:将局部变量B提供给Shell程序使用

[root@localhost ~]# B=100
[root@localhost ~]# export B
[root@localhost ~]# echo $B
100
[root@localhost ~]# env|grep B
B=100

也可以在给变量赋值的同时使用export命令

  • export 变量名=变量值

例如:使用export设置的变量在Shell以后运行的所有命令或程序中都可以访问到。

[root@localhost ~]# export C=100
[root@localhost ~]# echo $C
100
[root@localhost ~]# env|grep C
C=100

3.位置参数变量

当我们执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量,比如:./myshell.sh 100 200,这个就是一个执行shell的命令行,可以在myshell脚本中获取到 参数信息。

基本语法功能描述
$n n为数字,$0代表命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,如$(10)
$* 代表命令行中所有位置的参数,$*把所有参数看作一个整体
$@ 代表命令行中所有位置的参数,$@把每个参数区分对待
$# 代表命令行中所有位置参数的数量

例如:

[root@localhost myshell]# sh ./myshell.sh 100 200
./myshell.sh,100,200
100 200
100 200
参数的个数=2

[root@localhost myshell]# ./myshell.sh 1 2 3 4 5 6 7 8 9 10
-bash: ./myshell.sh: Permission denied
[root@localhost myshell]# chmod u+x myshell.sh
[root@localhost myshell]# ls -l 
total 4
-rwxr--r--. 1 root root 97 Jul 19 08:50 myshell.sh
[root@localhost myshell]# ./myshell.sh 1 2 3 4 5 6 7 8 9 10
./myshell.sh,1,2
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
参数的个数=10

4.预定义变量

就是shell设计者事先已经定义好的变量,可以直接在shell脚本中使用,和环境变量类似,所不同的是用户只能根据shell定义来使用这些变量,所有预定义变量都是由符合“$”和另一个符合组成的。

预定义变量描述
$$ 当前进程的进程号(PID)
$! 后台运行的最后一个进程号(PID)
$? 最后一次执行命令的返回状态,0表示没有错误,非0表示有错误

5.参数置换的变量

含义:通常是指将含义一个变量表达式的值赋给另一个变量。也是一种为变量赋值的方式。

说明:变量1、变量2用var1、var2表示,字符串用sring表示; var:type=value,“:”表示注解,提示变量的类型。var为要定义的变量,type为该变量期待的类型,value为赋给该变量的值。 本质上和var = value是一回事,只是加上了var的类型说明。 类型注解是一种提示,并非强制的。

格式var1为空var2不为空
var2=${var1:-string} var2=string var1不变 var2=$var1 var1不变
var2=${var1:=string} var2=string varvar2=string var1=string var2=$var1 ar1不变
var2=${var1:+string} var2为空 var1不变(也就是说var1也是空) var2=string var1不变
var2=${var1:?string} 输出格式:hell脚本名:var1=string 并退出shell var2不变 var2=$var1 var1不变

所有这形式中的参数既可以是位置参数,也可以是在另一个变量,只是用位置参数的情况比较多。

变量表达式

  • test是shell程序的一个表达式

语法:test [表达式]

字符串比较
字符串比较符号描述
= 比较两个字符串是否相同,相同则为“是”
!= 比较两个字符串是否相同,不同则为“是”
-n 比较字符串的长度是否大于0,如果大于0则是为“是”
-z 比较字符串的长度是否等于0,如果等于0则为“是”

例如:字符串比较的使用

[root@localhost ~]# str1=abcd
[root@localhost ~]# test $str1=abcd
[root@localhost ~]# echo $?
0

结果显示0表示字符串str1确实等于abcd.

test处理含有空格的变量时最好用引号将变量括起来,否则会出现错误的结果。因为Shell在处理命令行时将会去掉多余的空格,而用引号括起来则可以防止shell去掉这些空格。

数字比较

用于测试数字的大小

数字比较符合描述
-eq 相等
-ge 大于等于
-le 小于等于
-ne 不等于
-gt 大于
-lt 小于

例如:数字相等比较

root@localhost ~]# int1=1234
[root@localhost ~]# int2=01234
[root@localhost ~]# test $int1 -eq int2
-bash: test: int2: integer expression expected
[root@localhost ~]# echo $?
2
[root@localhost ~]# test "$int1 -eq int2"
[root@localhost ~]# echo $?
0

从上面可以看出,当test处理有空格变量时,不使用引号将变量括起来会导致错误。

例子:数字大于比较

[root@localhost ~]# int1=4
[root@localhost ~]# test “$int1 -gt 2"
> echo $?
> exit
> ^C
[root@localhost ~]# test "$int1 -gt 2"
[root@localhost ~]# echo $?
0

从上图例子可以看出,当引号使用中文格式时会出错。最后结果0表示字符int1的值确实大于2.

逻辑测试

用于测试文件是否存在

逻辑测试符合描述
! 与一个逻辑值相反的逻辑值
-a 两个逻辑值为"是"返回值才为“是”,反之为"否"
-o 两个逻辑值有一个为“是”返回值就为"是"

例如:逻辑测试

[root@localhost ~]# test -r "empty -a -s empty"
[root@localhost ~]# echo $?
1

结果显示表示empty存在且只读以及长度为0

文本操作测试

用于测试文件的文件操作逻辑

文件存在测试符合描述
-d 对象存在且为目录则返回值为“是”
-f 对象存在且为文件则返回值为“是”
-L 对象粗壮乃且为符号链接则返回值为“是”
-r 对象存在且可读则返回值为“是”
-s 对象存在且长度非0则返回值为“是”
-w 对象存在且可写则返回值为“是”
-x 对象存在且可执行则返回值为“是”
! 测试条件的否定

例子:文本操作测试

[root@localhost ~]# cat /dev/null>empty
[root@localhost ~]# cat empty
[root@localhost ~]# test -r empty
[root@localhost ~]# echo $?
0

结果显示0表示文件empty存在且只读

[root@localhost ~]# test ! -s empty
[root@localhost ~]# echo $?
0

结果显示0表示文件empty存在且文件长度为0

Shell条件判读语句

  • if
  • case
if条件语句

语法格式:

  • if-then-fi语句

例如:使用if-then-fi语句创建简单的shell程序( 创建文件名/root/continue,文件名如下)

[root@localhost ~]# vi /root/continue
[root@localhost ~]# cat /root/continue
#!/bin/bash
#filename:continue
echo -n "Do you want to continue: Y or N"
read ANSWER
if [$ANSWER=N -o $ANSWER=n]
then
exit
fi
[root@localhost ~]# bash /root/continue
Do you want to continue: Y or N
  • if-then-else-fi语句 例如:使用if-then-else-fi语句创建一个根据输入的分数判断分数是否及格的shell程序 文件名为/root/score,如下:
[root@localhost ~]# vi /root/score
[root@localhost ~]# cat /root/score
#!/bin/bash
#filename:score
echo -n "please input a score:"
read SCORE
echo "You input Score is $SCORE"
if [$SCORE -ge 60]
then
echo -n "Congratulation!You Pass the examination."
else
echo -n "Sorry!You Fall the examination!"
fi
echo -n "press any key to continue!"
read $GOOUT

运行Shell程序/root/score,输出内容如下

[root@localhost ~]# bash /root/score
please input a score:80
You input Score is 80
/root/score: line 6: [80: command not found
Sorry!You Fall the examination!press any key to continue!
[root@localhost ~]# ls -l /root/score
-rwxr--r--. 1 root root 278 Jul 19 19:26 /root/score
[root@localhost ~]# vi /root/score
[root@localhost ~]# bash /root/score
please input a score:80
You input Score is 80
Congratulation!You Pass the examination.press any key to continue!

上例中提示第6行"[80: command not found" 运行出错,经过排查命令运行权限及语句发现。是"["和变量"60"之前缺少空格引起。

case条件语句

为用户提供根据字符串或变量的值从多个选项中选择一项的方法。比如,通过计算string的值,将其结果一次与运算式exp-1和exp-2等进行比较,指导找到一个匹配的运算式为止。如果找到匹配项,则执行它下面的命令直到遇到一对分号(;;)为止。在case运算中也可以使用shell通配符(、?、[]).通常用作为case命令的最后运算式,以便在前面找不到任何相应的匹配项时执行"其他命令行"的命令。 例如:使用case语句创建一个菜单选择的shell脚本。文件名为/root/selection,内容如下:

[root@localhost ~]# vi /root/selection
[root@localhost ~]# cat /root/selection
#!/bin/bash
#filename:selection
#Display a menu
echo _
echo "1 Restore"
echo "2 Backup"
echo '3 Unload"
echo
#Read and excute the user's selection
echo -n "Enter Choice:"
read CHOICE
case "$CHOICE" in
1) echo "Restore";;
2) echo "Backup";;
3) echo "Unload";;
*) echo "Sorry $CHOICE is not a valid choice
exit 1
esac
[root@localhost ~]# bash /root/selection
_
1 Restore
2 Backup
3 Unload"
echo
#Read and excute the users selection
Enter Choice

Shell循环控制语句

  • for
  • while
  • ntil
for循环语句

for循环语句对一个变量的可能的值都执行一个命令序列。赋给变量的几个数值可以在程序中以数值列表的形式提供,也可以在程序以外以位置参数的形式提供。

变量名可以是用户选择的任何字符串,如果变量名是var,则在in之后给出的数字将按顺序替换循环命令列表的"$var".如果省略了in,则变量var的取值将是位置参数。对变量的每一个可能的赋值都将执行do和done之间的命令列表。

例如:使用for语句创建简单shell程序,文件名/root/for,如下

[root@localhost ~]# vi /root/for
[root@localhost ~]# cat /root/for
#!/bin/bash
#filename:for
for ab in 1 2 3 4
do
echo $ab
done

运行程序/root/for,输出内容如下:

[root@localhost ~]# bash /root/for
1
2
3
4

例子:使用for语句创建求命令行上所有整数之和的shell程序,文件名是/root/sum,如下

[root@localhost ~]# vi /root/sum
[root@localhost ~]# cat /root/sum
#!/bin/bash
#filename:sum
sum=0
for INT in $*
do
sum=$(expr $sum + $INT)
done
echo $sum
[root@localhost ~]# bash /root/sum 1 2 3 4 5
15
while循环语句

while语句是用命令的返回状态值来控制循环的。只要while的“若干个命令行1”中最后一个命令的返回状态为真,while循环就继续执行“若干个命令行2” 例子:使用while语句创建一个计算1~5的平方的shell程序,文件名是/root/zx,如下

[root@localhost ~]# vi /root/zx
[root@localhost ~]# cat /root/zx
#!/bin/bash
#filename:zx
int=1
while [ $int -le 5 ]
do
sq=$(expr $int * $int)
echo $sq
int=$(expr $int + 1)
done
echo "Job Completed"
[root@localhost ~]# bash /root/zx
1
4
9
16
25
Job Completed

例子:使用while语句创建一个工具输入的数值求累加和(1+2+3+4....+n)的shell程序,文件名/root/number,如下

[root@localhost ~]# vi /root/number
[root@localhost ~]# cat /root/number
#!/bin/bash
#filename:number
echo -n "Please Input Number:"
read NUM
number=0
sum=0
while [ $number -le $NUM ]
do
echo number
echo "$number"
number=$(expr $number + 1)
echo sum
echo "$sum"
sum=$(expr $sum + $number)
done
echo

[root@localhost ~]# bash /root/number
Please Input Number:4
number
0
sum
0
number
1
sum
1
number
2
sum
3
number
3
sum
6
number
4
sum
10
until循环语句

它和while类似。是另外一种循环结构,两者区别在于:while循环语句在条件为真时继续执行循环,二until循环语句则是在条件为假时继续执行循环。 例子:使用until语句创建一个输入exit退出的shell程序,文件名/root/hk,如下

[root@localhost ~]# vi /root/hk
[root@localhost ~]# cat /root/hk
#!/bin/bash
#filename:hk
echo "This example is for test until .... do "
echo "If you input [exit] then quit the system "
echo -n "please input:"
read EXIT
until [ $EXIT = "exit" ]
do
read EXIT
done
echo "OK!"
[root@localhost ~]# bash /root/hk
This example is for test until .... do 
If you input [exit] then quit the system 
please input:

特别注意:编辑命令时,双引号是英文状态下输入的双引号,如果中文状态下输入的双引号,会导致命令出错无法执行。

摘自:《Linux实用教程》人民邮电出版社出版发行 於岳编著

原文地址:https://www.cnblogs.com/mylive/p/11216189.html