shell脚本语言

shell脚本语言


shell是一个命令解析器,我们可以把很多要执行的命令以某种语言的方式组织起来交给shell去执行,这种命令的组织方式称为shell脚本语言。

xxx.sh是一个多个命令的组织文件,即shell脚本文件;shell脚本文件是一个普通文件,是shell基本语言的方式。

./xxx.sh把这些命令全部交给shell命令解析器去执行。命令解析器其实就是一个程序,如下所示:

/bin/bash
/bin/sh
/bin/dash
#都是shell解析程序
1. shell脚本文件

一个最简单的shell脚本文件: test.sh

#!/bin/dash #指定shell的解析程序
echo "hello world" #打印输出hello world

首先vi test.sh,然后编写程序,此后可能需要改变脚本文件test.sh的权限即chmod +x test.sh,最后运行脚本文件即./test.sh

2. shell变量

在shell脚本文件中,我们可以定义变量。shell变量没有类型的概念,或者说理解为全部都是字符串类型,shell变量不需要定义,直接用赋值就行。我们大致可以把shell变量分为4种。

变量赋值格式:变量名=值 即 name=value

变量的引用格式:$变量名 或者 ${变量名}

例如:

num = 520
k1=$num
k2=${num}
2.1 shell自定义变量

如:

num=520
data=`cmd` 
#`反撇号引用里面的cmd表示的那个命令或者说执行程序或者脚本的输出结果
data=`ls -l`
echo $data
2.2 shell位置变量

指的是传递给脚本文件或者函数的参数,如:

./test.sh 123 abc

在shell脚本或者shell函数中:

$0 #就表示第0个参数,即命令行程序名(./test.sh)
$1 #就表示第1个参数123
$2 $3···#表示的就是第2个参数到第···个参数的名字
$# #表示命令行参数的个数(不包括脚本名字)
$@ #包含所有的命令行参数
   #$@ = $1 $2 $3···
$* #包含所有的命令行参数
   #$* = $1C$2C$3···
   #C是IFS的第一个字符
   #IFS:内部域分隔符,即Internal Field Separetor
   #默认的值 空格 Tab 换行符
   #IFS="\t\n"
$? #表示前面一个命令或者程序的退出码(返回值exti值)
2.3 shell环境变量

环境变量:就是在同一个终端下面所有的进程都可以共享的变量

HOME:用户主目录的路径,如:

echo "$HOME"

PATH:命令或者可执行程序的搜索路径

例子:

gcc 1.c -o 1 
./1

为什么需要./1 执行程序,而不是直接1就可以执行 ;因为需要找到1这个可执行程序 。./1就是相当于告诉计算机在我当前目录下来找 ,如果没有告诉的话,则计算机就会去PATH指定的路径下查找1这个可执行文件。

可以通过echo "$PATH" 来查看默认的搜索路径,PATH的值为 dir1 : dir2 : dir3 … (每个路径之间用:隔开)。那么如果我们想直接敲1就可以执行程序的话 ,我们就应该把当前的路径添加到PATH中去
修改环境变量的值。
比如:

#export 环境变量名=新值
PATH=$PATH:/home/china

如果仅在终端修改环境变量, 这个环境变量的新值只在这个终端有效。那么如果想要全局也就是整个系统都有效的话 ,需要修改配置文件:/etc/profile
在这里插入图片描述

2.4 shell特殊变量
3. shell数组

​ 语句格式:数组名[下标]=value 下标即0,1,2,3,4,…

​ 引用单个数组元素格式:${数组名[下标]}
${数组名}–>在bash/dash中代表引用的是数组的第一个元素,数组名相当于首地址。
​ 引用整个数组(引用数组中所有的元素)元素格式:
${数组名[*]}或者${数组名[@]}

4. shell脚本语句
4.1说明性语句(注释)

#开头的行就是注释行

4.2 功能性语句

1)任意的操作系统的命令(如echo ls cd date clear…)
2)shell内部命令,自编程序 。如:read在shell中表示从终端获取数据 ,如:

read a b #这个代码就是说从终端获取两个字符串。 第一个字符串保存在变量a中,第二个字符串就保存在变量b中。 
4.2.1重定向问题

1)输入重定向
命令的输入请求通常是想标准输入设备(如键盘 )提交请求,我们也可以很方便地把输入重定向到一个设备/文件 ,这种情况我们称之为输入重定向。在获取输入的命令后添加 < filename ,该命令所有的输入都来自原filename指定的文件。

2)输出重定向
命令的输出通常提交给标准输出设备(如:终端)。也可以很方便地转向输出到另外一个设备/文件 ,则叫输出重定向。在输出命令的后面添加 > filename ,>先把filename文件的内容清空,再把数据输出到filename指定的文件中。在输出命令的后面添加 >> filename >>并不会清空filename原有的数据 ,而是以追加的形式把输出的数据输出到filename指定文件的末尾。

4.2.2 expr 算术运算命令

expr: 算术运算命令,expr主要用于进行简单的整数运算

包括: + - * / %

如: expr 1 + 2 //操作符和操作数之间一定要有一个空格!!!

练习: 写一个shell 计算两个整数的和,这两个整数通过参数传入or终端输入。

#!/bin/bash
sum=`expr $1 + $2`
echo $sum

read a b 
sum=`expr $a + $b`
echo $sum
4.2.3 test测试命令

test: 测试命令

test语句可以测试三种对象 :字符串、 整数 、文件。

test测试成功(满足条件) 返回0

test测试不成功(条件不满足) 返回1

a.字符串测试
= 测试两个字符串的内容是否完全一样

test "abc" = "abc" 
echo $? 

!= 测试两个字符串内容是否 不一样

test "abc" != "abcd"
echo $? 

-z zero测试字符串是否为空

test -z "" 
echo $? 

-n not null 测试字符串 是否不为空

test -n "abc"
echo $?				
			

以前的版本:

str= 
test -z $str #==>test -z   

会认为少了一个操作数,报语法错误 ,在测试字符串的时候 需要防止字符串为空做法:引用字符串 ,后面额外增加一个字符${str}x
如:判断变量a和变量b相不相等,test ${a}x = ${b}x

b.整数测试

a -eq b equal即测试两个整数是否相等
如:test 1 -eq 2
a -ne b not equal测试两个整数是否不相等
a -gt b greadter than >
a -ge b greadter or equal >=
a -lt b litter than <
a -le b litter or equal <=

c.文件测试
-d filename 测试filename是否为一个目录(directory)

test -d 1.c 
echo $? 

-f filename 测试filename是否为一个文件(file)
-L filename 测试filename是否为一个链接文件(Link)
-r filename 测试filename是否存在并且可读(read)
-w filename 测试filename是否存在并且可写(write)
-x filename 测试filename是否存在并且可执行(exculte)
-s filename 测试filename是否存在并且长度不为0(size)

f1 -nt f2 测试文件f1是否比f2更新,newer than
f1 -ot f2 测试文件f1是否比f2更旧 ,older than

最后 test命令可以用[]来代替
test expression <==> [ expression ]
如: test "abc" = "abc" 相当于 [ "abc" = "abc" ]

4.2.4 test复合表达式

组合两个或者两个以上的表达式称之为复合表达式 ,为了使用复合表达式,你可以用test([])内置的操作符,也可以用条件操作符。

1)使用test内置的操作符来创建复合表达式
-a and 并且 (与)
-o or 或者 (或)
例子: 我要测试从参数传入的第一个文件($1)是一个普通文件,并且他要比从参数传入的第二个文件($2)更新。

test -f $1 -a $1 -nt $2

例子: 5>4>3

test 5 -gt 4 -a 4 -gt 3

2)使用条件操作符来创建复合表达式
&& ||
例子:

[ 5 -gt 4 ] && [ 4 -gt 3 ] 
4.3结构性语句(分支结构、循环结构)
4.3.1 单路分支结构if

if command ; then ... 语句列表 else #else和后面的语句可以不要,只要一个if语句,不是省略的意思 ... 语句列表 fi
例子:
从键盘输入一个变量 //read
如果这个字符串是hello的话 //if test =
那么我就输出good //echo
如果不是,我就输出nogood

read a 
if [ $a = "hello" ] ; then 
echo "good"
else 
echo "nogood"
fi

练习: 从键盘输入一个整数 判断这个整数是不是奇数

read a
i=`expr $a % 2`
if [ $i -eq 1 ];then 
echo "jishu"
else 
echo "oushu"
fi
4.3.2 多路分支结构case

case 字符串变量 in 模式1) ...语句列表 ;; #类似于C语言中的break 但是shell中;;一定需要写的 模式2) ...语句列表 ;; ... 模式n) ...语句列表 ;; esac

case语句真正的强大之处在于他可以使用模式而不是固定的字符来匹配。一个模式是由一串正规字符和特殊的通配符(* ?)组成的字符串。该模式可以是正则表达式(有限支持 )

*shell通配符,代表任意多个(也可以是0个)字符。
? shell通配符, 代表任意一个字符。
例子: 从键盘输入一个文件名 判断该文件是什么类型。

read filename 
case $filename in 
	*.c) 
       echo "C source file"
	   ;;
	*.h) 
		echo "Header file"
		;;
esac
4.3.3 循环结构for

for 变量名 in 单词表 do ...循环体语句 done

类似于C语言的for
for(i=0;i<3;i++ ) { ...循环体语句 }

“单词表”:以空白符分隔开的字符串列表
如:a b c abc 123
for执行的次数就是“单词表”中单词的个数 ,并且每次执行时 “变量”的值就取下一个单词的值。
例子:

for i in a b c abc 
do 
	echo $i 
done 

for可以写成与C风格类型的循环

sum=0 
for((i=0;i<100;i++)) //步长为1
do 
sum=`expr $sum + $i`
done 
echo $sum 

练习:用shell求100之内满足3的倍数的数之和

sum=0 
for((i=0;i<100;i+=3))//步长为3
do 
	sum=`expr $sum + $i`
done 
echo $sum 

4.3.4循环结构while和until

while 命令或者表达式 do 循环体语句 done

相当于C语言中

while(表达式) { 循环体语句 }

until 命令或表达式 do 循环体语句 done
untilwhile的功能相似 ,不同的是unitl只有当测试的命令或者表达式值为假的时候才会执行循环体语句。当条件成立 ,跳出循环 ,这一点正好跟while是相反的。

练习:请你把下面这个while的例子改成until的用法

#!/bin/dash		 
i=0
while [ $i -le 100 ]
do 
	xxx;
done 
		
#改成
until [ $i -gt 100 ]
do 
	xxx;
done 
4.3.5 break 和 continue

5. shell函数
5.1函数的定义:
function_name() 
{
	//函数的内部具体实现;
	
}

function_name:你要定义的函数名字, 名字的取法和C语言类似,

做到“名如其意” “大驼峰”或者“小驼峰”。

5.2函数的调用:

function_name arg1 arg2 arg3 ...
在函数的内部
arg1 --> $1
arg2 --> $2
arg3 --> $3

5.3获取函数的返回值

通常有两种方式

1.ret=function_name arg1 arg2 arg3 ...

例子: 执行函数function_name时的标准输出的内容

#!/bin/dash	
sum() 
{
	a=$1
	b=$2
	s=`expr $a + $b`
    echo $s
}
	ret=`sum 1 2`

2.function_name arg1 arg2 arg3 ... ret=$?
$? 表示前面一个命令或者程序的退出码(返回值 exti值)
例子:

#!/bin/dash	
sum() 
{
	a=$1
	b=$2
	s=`expr $a + $b`
	return $s 
}
sum 1 2 #调用函数,参数为1和2
echo $?

练习: 写一个函数来判断一个从终端输入的数是不是质数

//C语言
void is_prime(int x)
{
	for(i=2;i<x;i++)
	{
		if(x % i == 0)
		{
			printf("not zhishu")
		}
	}
	printf("is zhishu")
}
			
int main() 
{
	int x;
	scanf("%d",&x);
	is_prime(x);
}
#shell 
is_prime() 
{
	i=2
	while [ $i -lt $1 ]#$1是函数调用时传递的第一个参数
	do 
		ret=`expr $1 % $i`
		if [ $ret -eq 0 ];then 
		echo "notzhishu"
		return 0
		fi
		i=`expr $i + 1`
		done
		echo "iszhishu"	
}
read n 
is_prime $n
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QJ敬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值