目录
- 三、Shell基本编程
- 1、Shell编程介绍
- 2、Shell脚本基本结构
- 3、Shell脚本及运行
- 4、Shell变量及表达式 - 变量类型
- 5、常用的Shell预定义变量
- 6、Shell变量及表达式 - 位置参数
- 7、Shell变量及表达式 –缺省参数
- 8、Shell变量表达式 概述
- 9、Shell脚本流程控制 - 分支语句if
- 10、Shell脚本流程控制 - 分支语句case
- 11、Shell脚本流程控制—循环控制 for
- 12、Shell脚本流程控制—循环控制 while
- 13、Shell脚本流程控制—循环控制 until
- 14、Shell脚本流程控制—函数
- 15、Shell脚本流程控制—数组
- 16、Shell脚本流程控制—序列函数seq
- 17、细节问题1:整数的四则运算
- 18、细节问题2:字符串函数
- 19、细节问题3:浮点数运算
三、Shell基本编程
1、Shell编程介绍
-
Linux体系中的shell编程在实现系统管理与维护、系统使用、用户环境定制等方面作用突出。
-
使用shell写的程序通常也称为脚本。
-
在用户主目录中,在/etc目录中,随处可见脚本文件。
-
脚本是由各种变量、表达式、命令等通过一定的逻辑组装而成的,具有顺序解释执行的特性。
2、Shell脚本基本结构
#!/bin/bash #脚本必须以#!开始
#! 表示:/bin/bash将执行该脚本文件中的程序
# 表示此后的字符串为注释
脚本支持:变量、表达式、流程控制、函数、注释,各种外部命令和程序调用、命令行参数、系统变量等等。
脚本就是将上述各种元素通过一定的逻辑关系进行组装已完成特定任务的程序。
3、Shell脚本及运行
1、利用vi编辑如下脚本并保持成 first.sh
#!/bin/bash
echo "Hello,welcome to Linux world"
echo "Today is $(date)"
2、设置执行权限
chmod u+x first.sh
3、执行脚本
./first.sh 或 sh first.sh 或 bash first.sh
4、Shell变量及表达式 - 变量类型
-
环境变量(系统工作环境需要的全局变量)
$PATH, $BASH, $HOME, TERM, $PWD
-
自定义变量(仅在脚本中使用局部变量)
语法格式:变量名=变量值 #变量名约定大写
# 例如 A=10;echo $A SA="hello Linux";echo $SA
-
只读变量
readonly 变量名
-
导出局部变量
export 变量名 或者 export 变量名=变量值
-
函数中的同名局部变量: local 变量名=变量值
注意问题
- 变量指向一个字符串(含有空格),则变量值必须使用双引号括起来。例如:
SA=“Hello Linux” - 引用时变量前加 SA SA$SA”
- 清除不需要的变量:unset 变量名
如:unset SA
5、常用的Shell预定义变量
变量名 | 功能 |
---|---|
$# | 位置参数的数量 |
$* | 所有位置参数的内容 |
$? | 命令执行后返回的状态 |
$$ | 当前进程的进程号 |
$! | 后台运行的最后一个进程号 |
$0 | 当前执行的进程名 |
6、Shell变量及表达式 - 位置参数
# 一个关于命令位置参数的脚本文件 arg.sh
#!/bin/bash
echo “完整的命令行:$0$*”
echo “程序是:$0”
echo “所有的参数:$*”
echo “参数个数:$#”
echo “第1个参数: $1”
问题:如果参数没输入,但程序中需要怎么办?
7、Shell变量及表达式 –缺省参数
比如脚本 mycal.sh 5 6 +; mycal.sh 5 6 *
如果没有输入 + 或者 * ,我能否默认取为 + 呢?而不是认为程序执行出错呢?
VAR=
{参数=word} :有则用参数, 否则两个用word
VAR=
{参数+word} :有则用word,否则不做
注意:上述四条经常用在位置参数的使用上。
# 脚本 mycal.sh
#!/bin/bash
LEFT=${1-100} #第一个参数缺省为100
RIGHT=${2-100} #第二个参数缺省为100
RE=`expr $LEFT + $RIGHT` #进行相加
echo "$LEFT + $RIGHT = $RE"
8、Shell变量表达式 概述
Shell中的变量表达式主要利用各种测试语句、条件来获得字符串、文件、数字等所处的状态。
表达式的操作符主要包括:
-
字符操作符: =, !=, -n , -z
-
数字操作符:-eq, -ne, -ge, -gt, -le, -lt
==, !=, >=, >, <=, <
-
-
逻辑操作符:!, -a, -o
-
文件操作符:-d, -f, -L,-r, -w, -x, -s, -e, -z,-c, -b,-o
可以使用 test 命令来测试上述各种表达式状态
test是Shell程序中的一个表达式,通过和Shell提供的if等条件语句相结合可以方便地测试字符串、文件状态和数字。其语法如下:
test [表达式]
表达式所代表的操作符有字符串操作符、数字操作符、逻辑操作符以及文件操作符。
作用:测试字符串是否相等,长度是否为零,字符串是否为NULL。
常用的字符串比较符号如下。
=:比较两个字符串是否相同,相同则为“是”。
!=:比较两个字符串是否相同,不同则为“是”。
-n:比较字符串的长度是否大于0,如果大于0则为“是”。
-z:比较字符串的长度是否等于0,如果等于0则为“是”。
# 在终端命令行输入
A=abcd; test $A=abcd; echo $?
A=" "; test –z $A; echo $?
test –n $A; echo $?
test –z “$A”; echo $?
B=1234; test $B –eq 1234; echo $?
test $B –gt 1000; echo $?
文件测试表达式通常是为了测试文件的文件操作逻辑,测试符号如下。
-d:对象存在且为目录,则返回值为“是”。
-f:对象存在且为文件,则返回值为“是”。
-L:对象存在且为符号连接,则返回值为“是”。
-r:对象存在且可读,则返回值为“是”。
-s:对象存在且长度非0,则返回值为“是”。
-w:对象存在且可写,则返回值为“是”。
-x:对象存在且可执行,则返回值为“是”。
逻辑比较:
test -f /etc/passwd –a –s /etc/passwd;echo $?
test -f /etc/passwd –a –d /etc/passwd;echo $?
test -d /root ; echo $?
test ! –z /etc/passwd; echo $?
9、Shell脚本流程控制 - 分支语句if
- Shell支持的流程控制语句主要有:
- 分支语句:if elif else fi, case … esac
- 循环语句:for, while, until
- 函数定义:function funname()
- 分支语句:if elif else fi, case … esac
if ((条件));then
语句
fi
或者
if [ 条件 ];then
语句
elif[ 条件 ];then
语句
else
语句
fi
#注意:[ 条件 ]中,条件前后必须留有一个空格
# [];then连在一起写,必须加上分号;
10、Shell脚本流程控制 - 分支语句case
echo -n "Input A="
read A
case $A in
1) echo "select 11";;
2) echo "select 22";;
*) echo "select else";;
esac
#---------
echo -n "Input A="
read A
case $A in
"fuzhou city") echo "select 11";;
"xiamen city") echo "seelct 22";;
*) echo "select else";;
esac
#如果是字符串变量且含有空格,则必须在匹配位置加上引号,如"fuzhou city"
菜单式
OPTIONS="fuzhou xiamen"
select opt in $OPTIONS; do
case "$opt" in
fuzhou) echo "select fuzhou";;
xiamen) echo "select xiamen";;
*) exit ;;
esac
done
#注意:输入1,opt=fuzhou;输入2,opt=xiamen。其他则结束
11、Shell脚本流程控制—循环控制 for
for 变量 [ in 数值列表] # for i in 1 2 3 4
do #省略 [ ] 则表示取编所有位置参数
命令
done
#--------
len=10; #指定循环次数
for (( i=0; i< "$len"; i=i+1 ))# 不可以用[]
do
命令
done
#---------
例子:实现1加到100
sum=0
for((i=1;i<101;i=i+1))
do
let sum=sum+$i
done
echo $sum
12、Shell脚本流程控制—循环控制 while
while 条件命令为真
do
命令
done
#------
while : #无限循环
do
命令
done
#------
例子:实现1加到100
k=1
sum=0
while [ $k -le 100 ] #[ 条件 ]中,条件前后必须留有一个空格
do
let sum=$sum+$k
let k++
done
echo $sum
13、Shell脚本流程控制—循环控制 until
until 条件命令为假
do
命令
done
#------
until : #无限循环
do
命令
done
#------
例子:实现1加到100
k=1
sum=0
until [ $k –gt 100 ]
do
let sum=$sum+$k
let k++
done
echo $sum
3种方法实现1加到100;4种i++;2种while
14、Shell脚本流程控制—函数
function funname()
{
[return 整数]
}
#------
例1:
function sum()
{
return $(($1+$2))
}
sum 10 20
echo "sum=$?"
#如果没有return则最后一条命令的返回值就是函数的返回值。
funname()
{
}
#注意:
#[1]函数必须先声明,才能调用
##[2]函数中的变量同全局变量名相同时,则
#使用 local val=value
#定义局部变量
#[3] 无需(不能)定义参数
#!/bin/bash
gsum=0
function sumn()
{ sum=0
for((i=1;i<=$1;i++))
do
let sum=$sum+$i
done
gsum=$sum
return $sum
}
sumn 10
echo "sum=$?"
#调用注意:
#[1] 直接传递参数
# 如 sumn 10
#[2] 函数就是命令,返回值只能通过 $?获取
# 如 echo "sum=$?"
#[3] 如果需要返回变量值, 则通过全局变量带回值
# 如 gsum
#!/bin/bash
gsum=0
function sumn()
{ local gsum=0
for((i=1;i<=$1;i++))
do
let gsum=$gsum+$i
done
return $gsum
}
sumn 10
echo "sum=$?"
echo $gsum
#调用注意:
#[1] 全局变量和局部变量的使用区别
# 如gsum
15、Shell脚本流程控制—数组
-
定义:
A=(元素列表,空格隔开)
下标从0开始 如A=(a b c d) -
数组长度
${#A[*]} -
引用第i个元素
KaTeX parse error: Expected '}', got 'EOF' at end of input: {A[i]} -
赋值
A[$i]=value -
以字符串输出所有元素
echo ${A[*]} -
循环输出所有元素
A=(a b c 123 ad 21)
Len=${#A[*]}
for((i=0;i<"$Len";i++))
do
echo ${A[$i]}
done
或者
for value in ${A[*]}
do
echo $value
done
16、Shell脚本流程控制—序列函数seq
#生成从1到100的100个元素的数组:
seq 1 100
Len=${#A[*]}
for((i=0;i<"$Len";i++))
do
echo ${A[$i]}
done
17、细节问题1:整数的四则运算
A=10
B=20
C=`expr $A + $B` # C=`expr $A \* $B`
D=$(($A+$B)) # D=$(($A\*$B)) D=$((A+B))
D=$[$A+$B] # D=$[A+B]
let E=A+B # let E=A*B
((F=A+B)) # ((F=A*B))
let A++ # ((A++))
let A+=10 # ((A+=10)) ((A*=10))
#注意:符号(( )) 或 [ ]中的变量可以不写引用符 $
18、细节问题2:字符串函数
字符串A="HELL:LINUX:WORLD"
#1. 获得字符串长度
LEN=${#A}
#2. 提取6-10字符
SUB1=${A:5:5}
结果 LINUX
#3. 从第6个字符开始提取
SUB2=${A:5}
结果 LINUX:WORLD
#4. 将符号:替换为符号/
REP=${A//:/\/}
结果 HELL/LINUX/WORLD
# 将符号:替换为cc
REP=${A//:/cc}
19、细节问题3:浮点数运算
#主要工具使用bc,(默认为整数运算,可以通过scale=bits精度小数点尾数,+,-,*,/,^,%)
#1.计算 5-2/3 保留4位小数
A=$(echo "scale=4; 5-2/3"|bc)
#2.
bc –q #进入bc计算器环境
scale=4 #设置小数点4位
5-2/3
quit #退出环境
#3.
bc –q file #执行file文件中的代码,类C代码
#prime.txt文件 使用 bc –q prime.txt
define is_prime(n)
{
auto prime,i;
prime=1;
for (i=2;i^2<=n;++i)
{
if (n%i==0){ prime=0; break; }
}
return prime;
}
print "\nPlease enter a positive integer n:\n";
n=read();
print "\n\n"
for (i=2;i<=n;++i)
{
if (is_prime(i)){ print i; print "\n"; }
}
quit;
=4; 5-2/3"|bc)
#2.
bc –q #进入bc计算器环境
scale=4 #设置小数点4位
5-2/3
quit #退出环境
#3.
bc –q file #执行file文件中的代码,类C代码
```shell
#prime.txt文件 使用 bc –q prime.txt
define is_prime(n)
{
auto prime,i;
prime=1;
for (i=2;i^2<=n;++i)
{
if (n%i==0){ prime=0; break; }
}
return prime;
}
print "\nPlease enter a positive integer n:\n";
n=read();
print "\n\n"
for (i=2;i<=n;++i)
{
if (is_prime(i)){ print i; print "\n"; }
}
quit;
专栏 《linux网络编程》 将持续更新中…
从linux 零基础 到 高并发服务器架构
您的每次点赞和收藏都是对我最大的鼓励!