Shell编程入门

1,创建shell脚本

新建文件test.sh,其中sh是拓展名,不影响脚本执行,只是为了见名知意,比如用php写的脚本,拓展名可以用php。test.sh内容如下:

#!/bin/bash
echo "bash shell"

#!是一个约定的标记,告诉系统这个脚本需要用什么解释器来执行,即使用哪一种shell。

2,运行shell脚本

1、 作为可执行程序

chmod +x ./test.sh #使脚本具有执行权限
./test.sh  #执行脚本

一定要写成./test.sh,而不是test.sh,运行其他二进制的程序也一样。直接写test.sh,Linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin,/sbin,/usr/bin,/usr,/sbin等在PATH里面,你的当前目录通常不在PATH里面,所以test.sh会找不到命令,要用./test.sh告诉系统,就在当前目录找。
运行结果如下:
在这里插入图片描述

2,作为解释器参数

这种方式是直接运行解释器,其参数就是shell脚本的文件名,如:

/bin/sh test.sh
sh test.sh

结果如上。这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用,

3,Shell变量

(1)显示给变量赋值

  • 命名只能使用数字,英文字母,下划线
  • 中间不能有空格,可以使用下划线
  • 不能使用标点符号
  • 不能使用bash里的关键字
#!/bin/bash
name="hello"
echo $name  #使用一个定义过的变量,只要在变量前面加美元符号即可
echo ${name} #变量的花括号可以选择,方便解释器识别边界

(2)使用语句给变量赋值

(3)只读变量

使用readonly命令可以将变量定义为只读变量,只读变量的值不能被改变

#!/bin/bash
name="hello"
readonly name
name="hi"
echo $name

运行结果如下,name的值依然是hello:
在这里插入图片描述

(4)删除变量

unset可以删除变量,但是不能删除只读变量。变量删除以后不能再使用。

#!/bin/bash
name="hello"
unset name
echo ${name}

运行结果如下:
在这里插入图片描述

(5)变量类型

  • 局部变量:局部变量在脚本或者命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  • 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  • shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量。有一部分是局部变量,这些变量保证了shell的正常运行。

(6)shell字符串

1、单引号
  • 单引号里的任何字符都会原样输出,单引号字符串的变量是无效的
  • 单引号字符串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但是可以成对出现,作为字符串拼接使用。
#!/bin/bash
name='java'
str='hello ${name}'
echo ${str}

输出如下:
在这里插入图片描述

2、双引号
  • 双引号里可以有变量
  • 双引号里可以出现转移字符(对单引号转义’似乎有问题)
#!/bin/bash
name="java"
str="hello \"${name}\""
echo ${str}

运行结果如下:
在这里插入图片描述

3、获取字符串长度,截取字串,查找字串
#!/bin/bash
name="hellojava"
echo ${#name}  #获取字符串长度
echo ${name:1:2} #获取字串,从第2个字符开始截取2个字符
echo `expr index ${name} lo` #查找子字符串,查找l或者o的位置,哪个先出现就计算哪个

运行结果如下:
在这里插入图片描述

(7)shell数组

shell支持一维数组。用括号来表示数组,用空格分开。也可以单独定义数组的各个分量。
读取数组的一般格式是${数组名[索引]},如果索引是@,可以获取数组中的所有元素。
获取数组长度的方式和获取字符串长度的方式相同。

#!/bin/bash
arr1=(hello java hi cpp)
arr2[0]=hello
arr2[1]=java
arr2[2]=hi
arr2[3]=cpp
echo ${arr1[@]}
echo ${arr1[0]}
echo ${arr2[@]}
echo ${arr2[1]}
echo ${#arr1[0]}  #获取数组单个元素的长度  
echo ${#arr1[@]}  #获取数组元素的个数

运行结果如下:
在这里插入图片描述

(8)注释

  • 单行注释 #
  • 多行注释
    :<<EOF
    注释内容
    EOF
    其中EOF也可以使用其他符号,例如
    :<<!
    注释内容
    !

4,shell传递参数

可以在执行shell脚本的时候向脚本传递参数,脚本内获取参数的方式是:$n。n表示一个数字,1代表第一个参数,2表示第二个参数。

#!/bin/bash
echo $# #传递到脚本的参数个数
echo "$*" #以一个单字符串显示所有向脚本传递的参数,在引用中将所有参数作为一个参数
for i in "$*";do
        echo $i
done
echo "$@" #与S#相同,但是使用的时候加引号,并在引号中返回每个参数
for i in "$@";do
        echo $i
done
echo $$ #脚本运行的当前进程ID
echo $! #后台运行的最后一个进程的ID
echo $- #显示shell使用的当前选项,与set命令相同
echo $? #显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

运行结果如下:

在这里插入图片描述

5,Shell基本运算符

(1)算术运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr,expr最常用。expr是一款表达式计算工具,使用它能完成表达式的求值操作。

#!/bin/bash
a=10
b=20
echo "a:${a} b:${b}"
echo `expr ${a} + ${b}`
echo `expr ${a} - ${b}`
echo `expr ${a} \* ${b}`
echo `expr ${a} / ${b}`
echo `expr ${a} % ${b}`
if [ ${a} == ${b} ]
then
        echo "a等于b"
fi
if [ ${a} != ${b} ]
then
        echo "a不等于b"
fi
a=${b}
echo "a:${a} b:${b}"

运行结果如下:
在这里插入图片描述

(2)关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

#!/bin/bash
a=10
b=20
echo "a:${a} b:${b}"
if [ ${a} -eq ${b} ]  #等于
then
        echo "a等于b"
else
        echo "a不等于b"
fi
if [ ${a} -ne ${b} ]  #不等于
then
        echo "a不等于b"
else
        echo "a等于b"
fi
if [ ${a} -gt ${b} ]  #大于
then
        echo "a大于b"
else
        echo "a小于b"
fi
if [ ${a} -lt ${b} ]  #小于
then
        echo "a小于b"
else
        echo "a大于b"
fi
if [ ${a} -ge ${b} ]  #大于等于
then
        echo "a大于等于b"
else
        echo "a并不大于等于b"
fi
if [ ${a} -le ${b} ]   #小于等于
then
        echo "a小于等于b"
else
        echo "a大于b"
fi

运行结果如下:
在这里插入图片描述

(3)布尔运算符

  • 与:-a
  • 或:-o
  • 非:!

(4)逻辑运算符

  • 逻辑AND:&&
  • 逻辑OR:||

(5)字符串运算符

  • = 检测两个字符串是否相等,相等为true
  • != 检测两个字符串是否不等,不等为true
  • -z 检测字符串长度是否为0,为0返回true
  • -n 检测字符串长度是否不为0,不为0返回true
  • $ 检测字符串是否为空,不为空返回true
#!/bin/bash
a="abc"
b="efg"
if [ ${a} = ${b} ]
then
        echo "a等于b"
else
        echo "a不等于b"
fi
if [ ${a} != ${b} ]
then
        echo "a不等于b"
else
        echo "a等于b"
fi
if [ -z ${a} ]
then
        echo "a字符串长度为0"
else
        echo "a字符串长度不为0"
fi
if [ -n ${a} ]
then
        echo "a字符串长度不为0"
else
        echo "a字符串长度为0"
fi
if [ ${a} ]
then
        echo "a字符串不为空"
else
        echo "a字符串为空"
fi

运行结果如下:
在这里插入图片描述

(6)文件测试运算符

文件测试运算符用于检测Unix文件的各种属性

#!/bin/bash
#-b file    检测文件是否是块设备文件,如果是,则返回 true。
#-c file	检测文件是否是字符设备文件,如果是,则返回 true。
#-d file	检测文件是否是目录,如果是,则返回 true。
#-f file	检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
#-g file	检测文件是否设置了 SGID 位,如果是,则返回 true。
#-k file	检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。
#-p file	检测文件是否是有名管道,如果是,则返回 true。
#-u file	检测文件是否设置了 SUID 位,如果是,则返回 true。
#-r file	检测文件是否可读,如果是,则返回 true。
#-w file	检测文件是否可写,如果是,则返回 true。
#-x file	检测文件是否可执行,如果是,则返回 true。
#-s file	检测文件是否为空(文件大小是否大于0),不为空返回 true。
#-e file	检测文件(包括目录)是否存在,如果是,则返回 true。
#-S file    判断某文件是否 socket。
#-L file    检测文件是否存在并且是一个符号链接。

6,echo命令

  • 显示普通字符串
#!/bin/bash
echo "hello java"  #字符串可以加双引号
echo hello java    #字符串不加双引号也行

运行结果如下:
在这里插入图片描述

  • 显示转义字符
echo "\"hello java\""
echo \"hello java\"

运行结果如下:
在这里插入图片描述

  • 显示变量
#!/bin/bash
read name
echo "hello ${name}"

运行结果如下:
在这里插入图片描述

  • 显示换行
#!/bin/bash
echo -e "OK \n"  # -e开启转义
echo "java"

运行结果如下:
在这里插入图片描述

  • 显示不换行
#!/bin/bash
echo -e "OK \c"
echo java

运行结果如下:
在这里插入图片描述

  • 显示结果定向至文件
#!/bin/bash
echo "hello java" > java.txt
  • 原样输出字符串,不进行转义或者取变量(单引号
#!/bin/bash
name="hello"
echo '${name}\"'

运行结果如下:
在这里插入图片描述

  • 显示命令的执行结果
#!/bin/bash
echo `date`

运行结果如下:
在这里插入图片描述

7,Shell printf 命令

printf模仿C程序库的printf程序,移植性更好。

#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

运行结果如下:
在这里插入图片描述
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

%-4.2f 指格式化为小数,其中 .2 指保留2位小数。

序列说明
\a警告字符,通常为ASCII的BEL字符
\b后退
\c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f换页
\n换行
\r回车
\t水平制表符
\v垂直制表符
\\一个字面上的反斜杠字符
\ddd表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd表示1到3位的八进制值字符

8,Shell test 命令

shell中的test命令用于检查某个条件是否成立,它可以进行数值,字符和文件三方面的测试。

数值测试

#!/bin/bash
num1=100
num2=100
if test $[num1] -eq $[num2] #代码中的 [] 执行基本的算数运算,例如:$[num1+num2]
then
	echo "两个数相等"
else
	echo "两个数不相等"
fi

-eq:等于则为真
-ne:不等于则为真
-gt:大于则为真
-ge:大于等于则为真
-lt:小于则为真
-le:小于等于则为真

字符串测试

#!/bin/bash
num1="java"
num2="Cpp"
if test ${num1} = ${num2}
then
	echo "两个字符串相等"
else 
	echo "两个字符串不相等"
fi

=:等于则为真
!=:不等于则为真
-z:字符串的长度为零则为真
-n:字符串的长度不为零则为真

文件测试

#!/bin/bash
cd /bin
if test -e ./bash
then
	echo "文件存在"
else
	echo "文件不存在"
fi

-e file 如果文件存在则为真
-r file 如果文件存在且可读则为真
-w file 如果文件存在且可写则为真
-x file 如果文件存在且可执行则为真
-s file 如果文件存在且至少有一个字符则为真
-d file 如果文件存在且为目录则为真
-f file 如果文件存在且为普通文件则为真
-c file 如果文件存在且为字符型特殊文件则为真
-b file 如果文件存在且为块特殊文件则为真

8,Shell 流程控制

if else

#!/bin/bash
a=10
b=20
if [ ${a} == ${b} ]
then 
	echo "a==b"
elif [ ${a} -gt ${b} ]
then
	echo "a>b"
elif [ ${a} -lt ${b} ]
then
	echo "a<b"
else
	echo "不符合条件"
fi

for 循环

#!/bin/bash
for loop in 1 2 3 4 5
do
	echo "The value is: ${loop}"
done

在这里插入图片描述

while 循环

#!/bin/bash
int=1
while((${int}<=5))
do
 echo ${int}
 let "int++"
done

在这里插入图片描述

case … esac

和其他语言的switch…case语句类似,是一种多分支选择结构,每个case分支用右圆括号开始,用;;表示break。

#!/bin/bash
read num
case ${num} in
	1) echo "你选择了1"
	;;
	2) echo "你选择了2"
	;;
	3) echo "你选择了3"
	;;
	4) echo "你选择了4"
	;;
	*) echo "你没有输入1-4之间的数组"
	;;
esac

运行结果如下:
在这里插入图片描述

跳出循环

break
#!/bin/bash
while :
do
	read num
	case $num in
		1|2|3|4|5) echo "你输入的数字是:$num"
		;;
		*) echo "你输入的数字不在1-5之间,游戏结束"
		break
		;;
	esac
done

运行结果如下:
在这里插入图片描述

continue

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

#!/bin/bash
while :
do
	read num
	case $num in
		2|3|4|5) echo "你输入的数字是:$num"
		;;
		1) echo "退出游戏"
		break
		;;
		*) echo "你输入的数字不在1-5之间,游戏结束"
		continue
		echo "游戏结束"
		;;
	esac
done

运行结果如下:
在这里插入图片描述

9,Shell 函数

(1)可以带function fun()定义,也可以直接fun()定义,不带任何参数
(2)参数返回,可以显示加return返回,如果不加,将以最后一条命令运行结果,作为返回值。

#!/bin/bash
demoFun(){
	echo "第一个函数"
}
echo "=========函数开始执行============"
demoFun
echo"==========函数执行结束============"

结果如下
在这里插入图片描述

#!/bin/bash
fun(){
        echo "输入第一个参数"
        read num1
        echo "输入第二个参数"
        read num2
#        return $(($num1+$num2))
        sum=$[ num1 + num2 ]
        return $sum
}
fun
echo "两数之和为: $?"

函数返回值在调用该函数后通过 $? 来获得。

#!/bin/bash
fun(){
	echo "The first parameter: $1"
	echo "The second parameter: $2"
	echo "The third parameter: $3"
	echo "The total: $#"
}
fun 1 2 3

运行结果:
在这里插入图片描述

参数处理说明
$#传递到脚本或函数的参数个数
$*以一个单字符串显示所有向脚本传递的参数
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与$*相同,但是使用时加引号,并在引号中返回每个参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

10,Shell 输入输出重定向

  • 输出重定向。
#!/bin/bash
who > who.txt #输出定向到文件中
who >> who.txt #输出追加到文件中
  • 输入重定向
#!/bin/bash
wc -l < who.txt 
wc -l < who.txt > res.txt
  • 重定向深入讲解
    标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
    标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
    标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
    默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:
command 2>file或者command 2>>file
如果希望将stdouthe stderr合并后重定向到file,可以这样写:
command > file 2>&1

  • Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。它的基本形式如下:
command << delimiter
document
delimiter
它的作用就是将document之间的内容作为输入传递给command。

#!/bin/bash
wc -l << EOF
	hello
	java
	cpp
EOF
  • /dev/null
    如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
#!/bin/bash
command > /dev/null 2>&1  #屏蔽stdout和stderr

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

11,Shell 文件包含

shell也可以包含外部脚本,这样可以很方便的封装一些公用的代码作为一个独立的整体。. filename或者source filename都可以。
test1.sh内容如下:

#!/bin/bash
name="java"

test.sh内容如下:

#!/bin/bash
. test1.sh
#source test1.sh
echo $name
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值