Shell脚本编程及示例和例题解析

sed及awk命令的总结地址:

http://10267776.blog.51cto.com/10257776/1696869




Shell脚本的说明:
shell脚本编程,实际上就是用vim编辑器编辑一个以.sh为结尾的脚本文件,在此脚本文件中使用Linux内部的一个或多个命令,通过编程语言以脚本运行的方式,一次性运行一次一个、一次多个或多次多个命令进行运算,并输出结果,及添加直观的注释。
Shell脚本的编辑标准格式:
使用vim编辑器编辑一个自定义创建的文件名并以.sh格式结尾—>
#!/bin/bash\\#!是一个约定的标记,他告诉系统这个脚本需要用什么解释权来执行。
#
脚本主体
\\脚本主体可直接编辑输入参数、命令、函数、shell编程语言等。且脚本主体所编辑的命令是依照顺序执行,即逐个执行。
\\ bash过程式编程:
顺序执行:逐个执行
选择执行:只执行其中一个分支
循环执行:一段代码要执行0,1或多遍
编程元素:变量、流程、函数
脚本编辑结束在末行输入:wq保存退出。
编辑结束首先要测试我们所编辑的脚本中是否有语法错误:
bash-n 脚本名;
测试语法无误,运行脚本:
bash-x 脚本名;
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
shell环境中的变量及参数:
变量:可变化的量,命名内存空间,bash的变量使用特点:弱类型、无须事先声明;
bash环境:
本地变量:当前shell进程;
环境变量:当前shell进程及其子进程;
局部变量:某个函数执行过程;
位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;


特殊变量:
$$
Shell本身的PID(ProcessID)
$!
Shell最后运行的后台Process的PID
$?
最后运行的命令的结束代码(返回值)
$-
使用Set命令设定的Flag一览
$*
所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$@
所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$#
添加到Shell的参数个数
$0
Shell本身的文件名
$1~$n
添加到Shell的各参数值。$1是第1参数、$2是第2参数…。


变量类型:
变量类型的作用:存储空间、运算、存储格式
数值,字符;
数值:整数、浮点数;
字符:ASCII

变量的具体说明:
本地变量:
name=value;
name: 我们自定义的变量名—>只能包含数字、字母和下划线;且不能以数字开头;
=:赋值符号;
value:我们需要给变量名赋予的值;
引用我们定义的变量:${name}在定义的变量名中含有下划线等特殊字符时必须使用{}来引用变量, $name


引用:


弱引用: ""双引号, 其内部的变量引用会被替换为变量值;


强引用:''单引号,其变量的变量引用会保持原有字符;


命令引用:`COMMAND`反引号, 也可使用$(COMMAND),引用命令的执行结果;


声明为整型:
declare -i name[=value]
let name=value
查看所有本地变量:set
变量的生命周期:
创建
销毁:
自动销毁:shell进程终止;
手动销毁:unset name
环境变量:
被“导出”的本地变量
export name[=value]
declare -x name[=value]
查看所有环境变量:env, printenv, export
销毁:
unset name


脚本:文本文件标准命名—>name.sh


运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后由bash进程负责解析并运行此逻辑;
启动脚本:
(1) # bash/PATH/TO/SCRIPT_FILE
(2) 给脚本一个执行权限即可直接通过脚本路径运行脚本:
# ./PATH/TO/SCRIPT_FILE
脚本格式我们在开始已经提过了,可回到首部查看;
我们在开始说过如何执行脚本,那执行脚本就必然会有成功或失败,当我们执行脚本以后可以使用 $? 命令查看上一条命令执行状态结果:
命令状态结果:
bash进程用于追踪执行的命令成功与否的状态:
0: 成功
1-255:失败
$?:上一条命令的执行状态结果;
我们可在脚本中自定义脚本的状态结果:
在脚本中敲入命令exit [n]—>n为我们想要输出的数字
注意:脚本中任何位置执行了exit命令即会终止当前shell进程;
条件测试:
界定程序执行环境;
(1) 根据运行的命令的状态结果;
(2) 测试表达式: EXPR 表达式
test EXPR
[ EXPR ]
` EXPR`

整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;
$A -gt $B:是否大于;是则为“真”,否则为“假”;
$A -ge $B: 是否大于等于;
$A -lt $B:是否小于;
$A -le $B: 是否小于等于;
$A -eq $B: 是否等于;
$A -ne $B:是否不等于;
字符串测试:ASCII数值越大,字符比较时其值越大;
"$A" > "$B":是否大于;
"$A" < "$B":是否小于;
"$A" == "$B":是否等于;
"$A" != "$B":是否不等于;
-z "$A":是否为空;空则为“真”,否则为“假”
-n "$A":是否不空;不空则“真”,空则为“假”
注意:应该使用` EXPRESSION `

文件测试:测试文件的存在性以及属性;
-e $file: 是否存在;存在则为“真”,否则为“假”;
-f $file:文件是否存在且为普通文件;
-d $file:文件是否存在且为目录;
-h $file:是否存在且为符号链接文件;
-b $file:是否存在且为块设备文件;
-c $file:是否存在且为字符设备文件;
-S $file:是否存在且为套接字文件;
-p $file: 是否存在且为管道文件;
-r $file: 当前用户对文件是否拥有读权限;
-w $file:当前用户对文件是否拥有写权限;
-x $file:当前用户对文件是否拥有执行权限;
-u $file:文件是否拥有SUID权限;
-g $file:文件是否拥有SGID权限;
-k $file:文件是否拥有sticky权限;
注:SUID,SGID,sticky为文件特殊权限,如果有同学不熟悉,可以自行复习。为了方便理解,我们这里还是列出来:
sticky bit (粘贴位)就是:除非目录的属主和root用户有权限删除它,除此之外其它用户不能删除和修改这个目录。
suid就是:让普通用户拥有可以执行“只有root权限才能执行”的特殊权限,sgid同理指”组“
-O $file: 当前用户是否为指定文件的属主;
-G $file: 当前用户是否为指定文件的属组;

双目操作符:
$file1 -nt $file2: file1是否新于file2, file1的最近一次的修改时间戳是否晚于file2的;
$file1 -ot $file2: file1是否旧于file2, file1的最近一次的修改时间戳是否早于file2的;
$file1 -ef $file2:file1与file2是否指向了同一个inode,
测试二者是否为同一个文件的硬链接;

特殊设备:
/dev/null: 空,bit buckets,吞下所有数据,并直接丢弃;
/dev/zero:吐出一堆0;
bash之条件判断(选择执行):
if/then ;case
if CONDITION; then
if-true-分支
fi
if CONDITION; then
if-true-分支
else
if-false-分支
fi
! CONDITION: 取反
-----------------------------------------------------------------------------------------------------------------
脚本参数(位置参数变量):
# ./script.sh/etc/fstab/etc/grub2.cfg
$0$1$2
注:为了更易于理解,我们进行下面说明:
参数$0—>shell自身文件,$1—>shell中定义的第一个参数,$2—>shell中定义的第二个参数,以此类推。
特殊变量:
$?: 命令的状态结果;
$#: 传递给脚本或函数的参数的个数;
$*和$@: 引用传递给脚本或函数的参数列表;
为了更直观的理解这些特殊变量,我们来做一个脚本小测试:
Shell脚本编程及示例和例题解析
文章图片

与用户交互:
read命令:
read [options] VAR...
-p "PROMPT"
-t timeout
示例:-t5 5秒后超时退出交互。
Shell脚本编程及示例和例题解析
文章图片

引用命令的执行结果;
(1) ls `which cat`
(2) lines=$(wc -l /etc/fstab | cut -d' ' -f1)
Shell脚本编程及示例和例题解析
文章图片

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
循环语句:循环就是通过循环编程对循环体进行多次运行,直到结果匹配给定的退出循环条件。
循环语句有:for, while, until
VARIABLE 定义的变量
for VARIABLE in LIST; do
循环体
done


LIST:是由一个或多个空格或换行符分隔开的字符串组成;
即 可使用LIST 给一个变量进行多次逐个赋值;
LIST 不为空时进入循环,LIST逐个赋值直到最后一个结束后循环结束,即退出循环;
for username in user1 user2 user3; do
循环体
done


示例:
添加10个用户,user1-user10;
Shell脚本编程及示例和例题解析
文章图片



LIST的生成方法:
(1) 整数列表
(a) {start..end}
(b) $(seq [start `step` end)
(2) 直接给出列表
(3) glob
(4) 命令生成


示例:数值列表
Shell脚本编程及示例和例题解析
文章图片



示例:glob,即定义参数变量为绝对路径下的文件:
#!/bin/bash
#
for filename in /var/log/*; do
file $filename
done
Shell脚本编程及示例和例题解析
文章图片



示例:命令生成列表
#!/bin/bash
#
for username in $(cut -d: -f1 /etc/passwd); do
echo "$username primary group: $(id -n -g $username)."
Done
Shell脚本编程及示例和例题解析
文章图片



Shell脚本中的算术运算:
+, -, *, /, %, **
(1) $[$A+$B]
(2) $(($A+$B))
(3) let VARIABLE=$A+$B
(4) VARIABLE=$(expr $A + $B)


示例:求100以内所以正整数之和;
Shell脚本编程及示例和例题解析
文章图片



增强型赋值:
+=
sum=$[$sum+$i]可写为:let sum+=$i
-=, *=, /=, %=
let count=$[$count+1]--> let count+=1 --> let count++
let count=$[$count-1]--> let count-=1 --> let count--


示例:显示/etc目录下所有普通文件列表,而后统计一共有多少个文件;
Shell脚本编程及示例和例题解析
文章图片

测试表达式:
整数测试:-gt, -lt, -ge, -le, -eq, -ne
字符串测试:==, >, <, !=, -z, -n, =~
注意:
(1) 字符串等会比较测试:[ "$hostname" == 'localhost']—>比较命令hostname的结果是否为localhost;
(2) 模式匹配测试:[[ "STRING" =~ PATTERN ]]
组合测试条件:
条件间逻辑运算:
与:多个条件要同时满足;
或:多个条件满足其一即可;
非:对指定的条件取反;
表达式组合:
与:` CONDITION1 -a CONDITION2 `
或:` CONDITION1 -o CONDITION2 `
非:[ ! CONDITION ]
命令组合:
与:COMMAND1 && COMMAND2<-- [ EXPR1 ] && [ EXPR2 ]
或:COMMAND1 || COMMAND2
非:! COMMAND
短路操作符:&&
false && true = false
false && false = false
第一个为假则不会运行第二个。
true && false = false
true && true = true
第一个为真则继续运行第二个,第二个为假则不会运行,为真则运行。
if COMMAND1; then
COMMAND2
fi
短路操作符:||
true || true = true
true || false = true
两个有一个为真则真;
false || true = true
false || false = false
两个全为假则假;
if ! COMMAND1; then \\如果命令1为 假则运行命令2.
COMMAND2
fi
COMMAND1 && COMMAND2 || COMMAND3与和或同时存在:
if COMMAND1; then \\如果命令1位真则运行命令2,否则运行命令3.
COMMAND2
else
COMMAND3
fi


示例:写一个脚本实现如下功能;
获取当前主机的主机名;如果当前主机的主机名为空,或者为localhost,则将其修改为www.magedu.com
Shell脚本编程及示例和例题解析
文章图片



练习:写一个脚本,打印九九乘法表;
循环嵌套
1X1=1
1X2=2 2X2=4
1X3=3 2X3=6 3X3=9
此练习的思路是:既然要打印99乘法表,是乘法就有被乘和乘两个变量,所以我们首先要定义两个变量的循环,其次进行两个变量的交叉循环运算,既然要打印为表,那么就要计算格式:
Shell脚本编程及示例和例题解析
文章图片



多分支的if语句:
单分支:
if CONDITION; then
if-true-分支
fi
双分支:
if CONDITION; then
if-true-分支
else
if-false-分支
fi
多分支:
if CONDITION1; then
if-CONDITION1-true-分支
elif CONDTION2; then
if-CONDITIO2-true-分支
...
else
if-ALL-false-分支
fi


示例:通过脚本参数传递一个文件路径给脚本,判断其类型;
Shell脚本编程及示例和例题解析
文章图片

由上面众多示例我们应该熟悉了怎么创建脚本及运行脚本、判断语法等,所以下面示例我们只给出脚本编程,不再进行运行测试;
示例:脚本可接受四个参数
start: 创建文件/var/lock/subsys/SCRIPT_NAME
stop: 删除此文件
restart: 删除此文件并重新创建
status: 如果文件存在,显示为"running",否则,显示为"stopped"
basename命令:取得路径的基名;
elif:if的特殊使用,多分支判断;
#!/bin/bash
#
prog=$(basename $0)
lockfile="/var/lock/subsys/$prog"
#echo $lockfile
if [ $# -lt 1 ]; then
echo "Usage: $prog start|stop|restart|status"
exit 1
fi
if [ "$1" == "start" ]; then
if [ -f $lockfile ]; then
echo "$prog is started yet."
else
touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
fi
elif [ "$1" == 'stop' ]; then
if [ -f $lockfile ]; then
rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
else
echo "$prog is stopped yet."
fi
elif [ "$1" == 'restart' ]; then
if [ -f $lockfile ]; then
rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
else
touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
fi
elif [ "$1" == 'status' ]; then
if [ -f $lockfile ]; then
echo "Running..."
else
echo "Stopped..."
fi
else
echo "Usage: $prog start|stop|restart|sttus"
exit 1
fi


case语句
简洁版多分支if语句;
使用场景:判断某变量的值是否为多种情形中的一种时使用;
语法:
case $VARIABLE in
PATTERN1)
分支1
; ;
PATTERN2)
分支2
; ;
PATTERN3)
分支3
; ;
...
*)
分支n
; ;
esac


\\PATTERN可使用glob模式的通配符:
*: 任意长度的任意字符;
?: 任意单个字符;
[]: 指定范围内的任意单个字符;
a|b: 多选1;


示例:提示键入任意一个字符;判断其类型;
#!/bin/bash
#
read -p "Plz enter a character: " char
case $char in
[a-z])
echo "A character."
; ;
[0-9])
echo "A digit."
; ;
*)
echo "A special character."
; ;
esac


示例:脚本可接受四个参数
start: 创建文件/var/lock/subsys/SCRIPT_NAME
stop: 删除此文件
restart: 删除此文件并重新创建
status: 如果文件存在,显示为"running",否则,显示为"stopped"
#!/bin/bash
#
prog=$(basename $0)
lockfile="/var/lock/subsys/$prog"
#echo $lockfile
if [ $# -lt 1 ]; then
echo "Usage: $prog start|stop|restart|status"
exit 1
fi
case $1 in
start)
if [ -f $lockfile ]; then
echo "$prog is started yet."
else
touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
fi
; ;
stop)
if [ -f $lockfile ]; then
rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
else
echo "$prog is stopped yet."
fi
; ;
restart)
if [ -f $lockfile ]; then
rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
else
touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
fi
; ;
status)
if [ -f $lockfile ]; then
echo "Running..."
else
echo "Stopped..."
fi
; ;
*)
echo "Usage: $prog start|stop|restart|sttus"
exit 1
esac#注:case语句以esac结束
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
shell中的流程控制语句:
循环语句:for, while, until
while循环:
while CONDTION; do
循环体
done
进入条件:当CONDITION为“真”;
退出条件:当CONDITION为“假”;
while CONDITION; do
循环体
控制变量的修正表达式
done


示例:求100以内所有正整数之和;
#!/bin/bash
#
declare -i sum=0
declare -i i=1
while [ $i -le 100 ]; do
let sum+=$i
let i++
done
echo "Sum: $sum."


示例:打印九九乘法表
#!/bin/bash
#
declare -i i=1
declare -i j=1
while [ $j -le 9 ]; do
while [ $i -le $j ]; do
echo -e -n "${i}X${j}=$[$i*$j]\t"
let i++
done
echo
let i=1
let j++
done


unitl循环:
until CONDITION; do
循环体
循环控制变量的修正表达式
done
进入条件:当CONDITION为“假”时
退出条件:当CONDITION为“真”时


示例:求100以内所有正整数之和
#!/bin/bash
#
declare -i sum=0
declare -i i=1
until [ $i -gt 100 ]; do
let sum+=$i
let i++
done
echo "Sum: $sum."


循环控制:
continue [n]:提前结束本轮循环,而直接进入下一轮;
break [n]:提前结束循环;


while循环:
while CONDITION; do
.......
if CONDITION2; then
break [n]
fi
done
while CONDITION; do
......
if CONDITION2; then
continue [n]
fi
......
done


示例:求100以内所有偶数之和;
#!/bin/bash
#
declare -i sum=0
declare -i i=0
while [ $i -le 100 ]; do
let i++
if [ $[$i%2] -eq 1 ]; then
echo "$i is a odd."
continue
fi
let sum+=$i
done
echo "Sum: $sum."
死循环:
while true; do
循环体
if CONDTION; then
break
fi
done
until false; do
循环体
if CONDITION; then
break
fi
done


示例:每隔3秒钟查看当前系统上是否有名为“gentoo”的用户登录;
如果某次查看gentoo登录了,则显示gentoo已经登录;
如果未登录,就显示仍然未来,并显示这是已经是第多少次查看了;
#!/bin/bash
#
username=$1
declare -i count=0
while true; do
if who | grep "^$username" &> /dev/null; then
echo "$username is logged."
break
else
let count++
echo "$count $username is not login."
fi
sleep 3
done
#!/bin/bash
#
declare -i count=0
username=$1
if [ $# -lt 1 ]; then
echo "At lease one argument."
exit 1
fi
if ! id $username &> /dev/null; then
echo "No such user."
exit 2
fi
until who | grep "^$username" &> /dev/null; do
let count++
echo "$count $username is not login."
sleep 3
done
echo "$username is logged on."


while循环的特殊用法:
遍历文件的每一行:
while read VARIABLE; do
循环体
done < /PATH/FROM/SOME_FILE


示例:找出UID为偶数的所有用户,显示其用户名和ID号;
#!/bin/bash
#
while read line; do
userid=$(echo $line | cut -d: -f3)
if [ $[$userid%2] -eq 0 ]; then
echo $line | cut -d: -f1,3
fi
done < /etc/passwd


for循环的特殊用法:
for ((expr1; expr2; expr3)); do
循环体
done
expr1: 定义控制变量,并初始赋值;
expr2: 循环控制条件;
进入条件:控制条件为“真”
退出条件:控制条件为“假”
expr3: 修正控制变量


示例:求100以内所有正整数之和;
#!/bin/bash
#
declare -i sum=0
for ((i=1; i<=100; i++)); do
let sum+=$i
done
echo "Sum: $sum."


函数:
function: 功能
把一段具有独立功能代码封装在一起,并给予命名;后续用到时,可直接通过给定函数名来调用整体代码;
函数作用:
代码重用;
模块化编程;
函数的使用方法:
先定义:编写函数代码
后调用:给出函数名,还可按需传递参数
定义方法:
(1) function f_name {
函数体
}
(2) f_name() {
函数体
}
调用函数:
f_name [argu1, argu2, ...]
自定义函数状态返回值:
return [#]
0: 成功
1-255:失败
注意:函数代码执行时,一旦遇到return,函数代码终止运行,函数返回;


示例:此前的服务脚本
#!/bin/bash
#
prog=$(basename $0)#获取目录根路径
lockfile="/var/lock/subsys/$prog"
#echo $lockfile
if [ $# -lt 1 ]; then
echo "Usage: $prog start|stop|restart|status"
exit 1
fi
start() {
if [ -f $lockfile ]; then
【Shell脚本编程及示例和例题解析】echo "$prog is started yet."
else
touch $lockfile && echo "Starting $prog ok..." || echo "Starting $prog failed..."
fi
}
stop() {
if [ -f $lockfile ]; then
rm -f $lockfile && echo "Stop $prog ok...." || echo "Stop $prog failed..."
else
echo "$prog is stopped yet."
fi
}
restart() {
if [ -f $lockfile ]; then
rm -f $lockfile && touch $lockfile && echo "Restarting $porg ok..."
else
touch $lockfile && echo "$prog is stopped, Starting $prog ok...."
fi
}
status() {
if [ -f $lockfile ]; then
echo "Running..."
else
echo "Stopped..."
fi
}
case $1 in
start)
start
; ;
stop)
stop
; ;
restart)
restart
; ;
status)
status
; ;
*)
echo "Usage: $prog start|stop|restart|sttus"
exit 1
esac
示例:判断用户的ID号的奇偶性;
#!/bin/bash
#
evenid() {
if [ $# -lt 1 ]; then
return 1
fi
if ! id $1 &> /dev/null; then
return 2
fi
userid=$(id -u $1)
if [ $[$userid%2] -eq 0 ]; then
echo "$1, Even user ID."
else
echo "$1, Odd user ID."
fi
}
evenid root
evenid
echo $?
evenid rooooooooooooot
echo $?


-------------------------------------------------------------------------------------------
模块化编程
功能:把脚本文件中的代码分隔为多段,放在不同的文件中
假设/root/bin/srv目录有两个文件:
(1) 函数文件
(2) 脚本文件
为脚本使用配置文件
一个文件中只定义变量
脚本文件source此变量定义的文件
可将脚本分为两个文件,在运行的文件中使用source PATH引用另一个配置文件;
变量的作用域:
局部变量:在当脚本中存在其他变量与函数中定义的变量重复时时,需要使用local命令来使函数中的变量变为局部变量:
local VARIABLE=value
局部变量存活时间:
函数执行开始,至函数返回结束;
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
作业:
1写一个脚本
如果某路径不存在,则将其创建为目录;否则显示其存在,并显示内容类型;
Shell脚本编程及示例和例题解析
文章图片

2 写一个脚本,完成如下功能;判断给定的两个数值,孰大孰小;给定数值的方法:脚本参数,命令交互;
Shell脚本编程及示例和例题解析
文章图片

3.求100以内所有偶数之和;
使用至少三种方法实现;
1).seq语法表示0 2 100:0-100 每次隔2.
Shell脚本编程及示例和例题解析
文章图片

2).与上个方法不同的就是变量i的赋值方式不同:
Shell脚本编程及示例和例题解析
文章图片

3).此方法使用函数调用法:
Shell脚本编程及示例和例题解析
文章图片

4.写一个脚本(1) 传递两个文本文件路径给脚本;
(2) 显示两个文件中空白行数较多的文件及其空白行的个数;
(3) 显示两个文件中总行数较多的文件及其总行数;
Shell脚本编程及示例和例题解析
文章图片

5.写一个脚本
(1) 提示用户输入一个字符串;
(2) 判断:
如果输入的是quit,则退出脚本;
否则,则显示其输入的字符串内容;
Shell脚本编程及示例和例题解析
文章图片

6.写一个脚本,打印2^n表;n等于一个用户输入的值;
Resolution:这题主要思路就是首先定义一个循环变量i,然后使用read读取交互输入的$num,接着进行循环运算,定义退出循环条件:使循环变量$i小于$num,i从0开始赋值,然后进行数值运算:2**$i。
Shell脚本编程及示例和例题解析
文章图片

7.写一个脚本,写这么几个函数:函数1、实现给定的两个数值的之和;函数2、取给定两个数值的最大公约数;函数3、取给定两个数值的最小公倍数;关于函数的选定、两个数值的大小都将通过交互式输入来提供。
由于此处脚本过长,所以此处给出编程代码,并附上脚本运行结果:
此处本人写出两套方案,一个简单易懂,一个细化分类:
#!/bin/bash
#

if [[ $# -le 2 ]]; then
echo "plz input two number and use space to isolation them!"
fi
function add() {
echo "The two num sum:$1+$2=`expr $1 + $2`"
}
add $1 $2


declare -i big
declare -i sma
if [ $1 -gt $2 ]; then
big=$1
sma=$2
else
big=$2
sma=$1
fi


gcdlcm(){
i=1#定义一个循环变量
GCD=1#定义最大公约数
LCM=1#定义最小公倍数
btmp=1#定义用户输入的较大的一个变量除以循环变量的值
stmp=1#定义用户输入的较小的一个变量除以循环变量的值
while [ $i -le $sma ]; do#定义循环条件,循环变量小于或等于用户输入的较小的变量
btmp=`expr $big % $i`#求值
stmp=`expr $sma % $i`#求值
if [ $btmp -eq 0 ]; then#判断值得余数是否为0
if [ $stmp -eq 0 ]; then#同上
gcd=$i#如果值得余数为0,则获取最大公约数的值
fi#判断结束
fi
i=`expr $i + 1`#i变量循环,直到i等于用户输入的较小的数为止退出循环。
done#当i=$sma,退出循环
lcm=`expr $sma / $gcd`#根据最小公倍数公式求值
lcm=`expr $lcm \* $big`#同上,求最小公倍数公式为:lcm=$sma*$big%gcd
echo "lcm:$lcm"#输出lcm值
echo "gcd:$gcd"#输出gcd值
}


第二种方法:
#!/bin/bash
#
if [[ $1 -eq "" ]]; then
echo 'plz input the first number'
exit 1
fi
if [[ $2 -eq "" ]]; then
echo 'plz input the second number'
exit 2
fi
function add() {
sum=$[$1+$2]
echo "the sum is $sum"
}
add $1 $2
declare -i max
declare -i min
if [[ $1 -gt $2 ]]; then
max=$1
min=$2
elif [[ $1 -lt $2 ]]; then
max=$2
min=$1
else
max=$1
min=$2
fi
function gong() {
r=$[$max%$min]
temp=$min
declare -i a
declare -i b
if [[ $r -eq 0 ]]; then
echo "gongyue is $min"
echo "gongbei is $max"
else
while [[ $r -ne 0 ]]; do
a=$2
b=$r
r=$[$a%$b]
done
gongyue=$b
gongbei=$[$1*$2/$b]
echo "gongyue is $gongyue"
echo "gongbei is $gongbei"
fi
}
gong $1 $2
Shell脚本编程及示例和例题解析
文章图片



转载于:https://blog.51cto.com/summer37/1695093

    推荐阅读