Shell 既是命令解释程序,又是一种高级程序设计语言。shell是解释型语言

编写Bash脚本程序有两种方式:可以输入一系列命令,也可以把命令保存到一个文本文件中,然后作为程序来调用

Shell脚本

第一个Shell脚本(以.sh为后缀)

#! /bin/bash                                                                                                                         
  2 echo "Hello Shell"
  3 echo $PWD

Shell编程1_shell

相要执行该文件,需要给文件设置可执行权限

chmod u+x 1.sh

执行

方法1:

./程序名

Shell编程1_shell_02

方法2:

bash 程序名

bash 1.sh #方法2

Shell编程1_shell_03

方法3:将文件路径添加到整个环境变量中,在任何目录下都可以编译和执行该脚本

export PATH=该文件路径:$PATH

1.sh

#方法3
export PATH=/root/test:$PATH  #路径间用:分割,$PATH一定要加上
1.sh

Shell编程1_shell_04

Linux修改PATH环境变量 - 简书 (jianshu.com)

Shell编程1_shell_05

/root/test已被加入到环境变量中,路径间用:分割,

使用方法3添加环境变量时,$PATH一定要加上,如果不加,bash大部分命令均不可用,如图,不过这样修改的环境变量是临时的,仅对本次登录有效,可以退出重新登陆就可以了

Shell编程1_shell_06

shell位置参数和变量

由系统提供的参数称为位置参数。位置参数的值可以由$N得到,N是一个数字,如果为1,参数的值即$1。类似C语言中的数组,Linux会把输入的命令字符串分段并给每段主行标号。标号从0开始,第0号为程序名字,从1开始就表示传递给程序的参数,即S0示程序的名字,$1表示传递给程序的第一个参数,以此类推。

命令不计算在参数内

位置参数及

内部参数

说明

读写特性

$0 

$hell脚本的文件名字

只读

$1-$9

命令行参数1-9的值

只读

$*

命令行中所有的参数,如果$*被引号""包括,即"$*",指各个参数之

间用环境变量 IF$中的第一个字符分隔开。

只读

$@

命令行中所有的参数,它是$*的一种的变体。如果$@被引号""包括,即

"$@",指它不使用IF$环境变量,所以当IF$为空时,参数的值不会结

合在一起。这就是$@同$*在被""包括的时候的差别,其他时候这二者是

等价的

只读

$#

命令行参数的总个数

只读

$$

$hell脚本进程的ID号

只读

$?

最近一次命令的退出状态

只读

$!

最近一次后台进程的ID号

只读

Shell编程1_shell_07

如果Shell脚本中使用的参数不超过9个,用$1~$9即可,如果大于9,可以用

shift命令

shift能够将命令接收到的参数逐个向左移动一位

语法格式:shift [N]

功能:把命令行参数向左移动N个位置

#! /bin/bash
  echo "程序名:$0"                                                                                                                    
  echo "所有参数:$@"
  echo "前三个参数:$1 $2 $3"
  shift
  echo "程序名:$0"                                                                                                                   
  echo "所有参数:$@"
  echo "前三个参数:$1 $2 $3"
  shift 2
 echo "程序名:$0"
 echo "所有参数:$@"
 echo "前三个参数:$1 $2 $3"
 exit 0

Shell编程1_shell_08

set设置位置参数

Linux set命令教程:如何优雅地设置和取消shell变量和选项(附实例详解和注意事项)_set设置的变量怎么取消-CSDN博客

Shell编程1_shell_09

Shell编程1_shell_10

Shell 变量可以分为两大类型:环境变和用户定义变量。环境变量用来定制您的 Shel的运行环境,保证Shell命令的正确执行。所有环境变量会传递给shell 的子进程。这些变量大多数在/etc/profile文件中初始化,而/etc/profile是在用户登录的时候执行的。

环境变量

说明

读写特性

$HOME

当前用户的主目录

读写

$PATH

以冒号分隔的用来搜索命令的目录列表

读写

$PS1

命令提示符通常是$字符,但在Bash中,您可以使用一些更复杂的值。例

如,字符串[u@\h\W]$就是一个流行的默认值,它给出用户名、机器名和

当前目录名,当然也包括一个$提示符

读写

$PS2

二级提示符,用来提示后续的输入,通常是>字符 

读写

$IFS

内部域分隔符,当shell 读取输入时,用来分隔单词的一组字符,它们通

常是空格、制表符和换行符

读写

Shell编程1_shell_11

Shell编程1_shell_12

修改IFS为,

#! /bin/bash
#修改IFS
#在修改IFS前,保留原IFS
IFS_OLD="$IFS"
#设置,为内部域分隔符
IFS=','
string="a,b,c d,e f,G"
for i in $string
do
    echo $i
done
IFS=$IFS_OLD

exit 0

Shell编程1_shell_13

命令替换

Shell 中有两种方式可以完成命令替换,一种是反引号` `,一种是$(),使用方法如下:

  1. variable=`command`
  2. variable=$(commands)

第一种方式不支持嵌套使用,第二种支持嵌套使用

Shell命令替换:将命令的输出结果赋值给变量 (biancheng.net)

变量替换:

$variable 这种写法是 ${variable} 的简化形式

4.1 变量替换 | Bash脚本进阶指南 (gitbook.io)

例:第二章课后第5题《Linux高级程序设计》)

编写一个 shen 脚本,它带一个命令行参数,这个参数是一个文件。如果这个文件是一个普通文件,则打印文件所有者的名字和最后的修改日期;如果程序带有多个参数,则输出出错信息

  • 命令行参数
  • 文件类型判断
#! /bin/bash
#102第5题
N=$#
#echo "参数个数:$N"
filename="$1"
set  $(ls -il $filename)
if [[ $N -eq 1 ]]&&[[ -f $filename ]]
then
	echo "文件名 文件所有者	最后修日期"
	echo "$filename	$4          	$7-$8-$9"
	exit 0
elif [ $N -gt 1 ]
then
	echo "ERROR!输入参数过多。"
	exit 1
else
	echo "ERROR!"
	exit 1
fi

变量的声明和赋值

用户定义的 Shell 变量的名字可以包括数字、字母和下划线,变量名的开头只允许是母或下划线。变量名中的字母是大小写敏感的,变量名的长度没有限制。

Bash变量默认是字符串,可以通过declare和typeset命令来声明变量,typeset 命令是 bash 的内建命令,是命令 declare 的别名,两者是完全一样的,用来声明 shell 变量,设置变量的属性。

格式:declare [+/-][rxi][name=设置值] 或 declare -f

  • -a 声明name是一个数组
  • -f 声明name是一个函数
  • -i 声明name是一个整数
  • -r 声明name是只读变量
  • -x 声明name变量可以被子进程访问到,称为全局变量
  • - 取消变量属性,但是 +a 和 +r 无效,无法删除数组和只读属性,可以使用 unset 删除数组,但是 unset 不能删除只读变量,所以设置变量为“只读”时需要慎重,因为这个不可逆的操作

Shell编程1_shell_14

单双引号的使用

单引号

单引号是全引用,被单引号括起的内容不管是常量还是变量都不会发生替换

也就是说单引号定义字符串所见即所得,将单引号内的内容输出,看到的是什么就会输出什么。

Shell编程1_shell_15

双引号

双引号是部分引用,被双引号括起的内容常量还是常量,变量则会发生替换,替换成变量内容。

Shell编程1_shell_16


变量的输入

read可以读取键盘输入的字符。read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量,用 IFS(内部字段分隔符)变量中的字符作为分隔符。

格式:read [options] variable-list

  • -a name 把值读入name数组中
  • -e 用于限定最多可以有多少字符可以作为有效读入。例如echo –n 4 value1 value2,如果我们试图输入12 34,则只有前面有效的12 3,作为输入,实际上在你输入第4个字符‘3’后,就自动结束输入。这里结果是value为12,value2为3。且echo输出时光标从该行输出

Shell编程1_shell_17

详细参考:Shell中read的选项及用法_shell read -a-CSDN博客

控制结构语句

if-then-elif-then-else-fi语句

if [ 条件判断式 ]
	then
		程序
 elif [ 条件判断式 ]
 	then
  	程序
else
	程序
fi

注意事项:

  • if语句使用fi结尾,和一般语言使用大括号结尾不同
  • [ 条件判断式 ]也可使用test 表达式命令判断,注意中括号和条件判断式之间必须有空格。
  • then后面跟符合条件之后执行的程序,可以放在[]之后,用“;”分割。也可以换行写入,就不需要“;”了。

字符串比较

  • string1=string2 如果相同则为真(表达式值为0)
  • string1!=string2 如果不相同则为真(表达式值为0)
  • -z 判断字符串是否为空串,如果是,则为真。
  • -n 判断字符串是否为空串,如果不是空串(长度大于0),则为真

算术比较

用于整数间比较

算术比较

结果

expressionl -eq expression2

如果两个表达式相等则结果为真

expressionl -ne expression2

如果两个表达式不等则结果为真

expression1 -gt expression2

如果expression1大于expression2 则结果为真

expressionl -ge expression2

如果 expression1 大于或等于 expression2 则结果为真

expressionl -It expression2

如果expression1 小于 expression2则结果为真

expressionl -le expression2

如果expression1 小于或等于expression2 则结果为真

!expression

如果表达式为假则结果为真,反之亦然

文件测试

文件条件测试

结果

-d file

如果文件是一个目录则结果为真(值为0)

-e file

如果文件存在则结果为真

-f file

如果文件是一个普通文件则结果为真

-g file

如果文件的SGID位被设置则结果为真

-r file

如果文件可读则结果为真

-s file

如果文件的长度不为0则结果为真

-u file

如果文件的SUID位被设置则结果为真

-w file

如果文件可写则结果为真

-x file

如果文件可执行则结果为真

Shell编程1_shell_18


例:(第二章课后第6题《Linux高级程序设计》)

编写一个Bash 脚本程序,用for循环实现将当前目录下的所有.c文件移到指定的目录下,最后在显示器上显示指定目录下的文件和目录。

Shell编程1_shell_19

#! /bin/bash
declare -a arr
arr=$(find $PWD -name "*.c") #未设定搜索层数,可能会导致将其子目录下的.c文件也复制
#arr=$(find $PWD -maxdepth 1 -name "*.c") #设定层数
for i in $arr
do
	#echo $i
	mv $i $1
done

ls -l $1
exit 0

Shell数学计算(算术运算,加减乘除运算) (biancheng.net)

Shell (()):对整数进行数学运算 (biancheng.net)

for语句

1.第一种格式

for  变量  in  列表
do
    操作
done
#! /bin/bash
data="a,b,c,d,e,f"
IFSBAK=$IFS #更改分隔符为,
IFS=,
for i in $data
do
	echo $i
done
IFS=$IFSBAK
exit 0

Shell编程1_shell_20

2,.第二种格式(与C语言模式下for相似)

for  ((初始化表达式; 条件表达式; 更新循环变量表达式))
do
    循环语句
done
#! /bin/bash
declare -i i=0
for(( i=0;i<= 4; i++)) #和c语言中的写法类似
do
	echo $i
done

while循环

while 表达式
    do
        command...
    done
#! /bin/bash
i=0
while [ $i -le 10 ]
do
	echo $i
#	i=$(( i+1 ))
	((i++))
done
exit 0

until语句

until语句 :提供循环执行,它与while循环相反, until循环将反复执行直到条件为真就结束循环,而while循环条件为假就结束循环。

使用格式:

until [ 测试条件 ]

do

语句 #可以是多条语句

done

case语句

case expression in
    pattern1)
        statement1
        ;;
    pattern2)
        statement2
        ;;
    pattern3)
        statement3
        ;;
    ……
    *)
        statementn
esac


#! /bin/bash
read i
case $i in
	1|2) echo "hello"
		;;
	3) echo "good"
		;;
	4) echo "moring"
		;;
	*) echo "else"
	esac
exit 0


Shell编程1_shell_21

break和continue

break跳出循环,continue跳出本次循环

exit语句

exit [n]