Shell 既是命令解释程序,又是一种高级程序设计语言。shell是解释型语言
编写Bash脚本程序有两种方式:可以输入一系列命令,也可以把命令保存到一个文本文件中,然后作为程序来调用
Shell脚本
第一个Shell脚本(以.sh为后缀)
#! /bin/bash
2 echo "Hello Shell"
3 echo $PWD
相要执行该文件,需要给文件设置可执行权限
chmod u+x 1.sh
执行
方法1:
./程序名
方法2:
bash 程序名
bash 1.sh #方法2
方法3:将文件路径添加到整个环境变量中,在任何目录下都可以编译和执行该脚本
export PATH=该文件路径:$PATH
1.sh
#方法3
export PATH=/root/test:$PATH #路径间用:分割,$PATH一定要加上
1.sh
Linux修改PATH环境变量 - 简书 (jianshu.com)
/root/test已被加入到环境变量中,路径间用:分割,
使用方法3添加环境变量时,$PATH一定要加上,如果不加,bash大部分命令均不可用,如图,不过这样修改的环境变量是临时的,仅对本次登录有效,可以退出重新登陆就可以了
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脚本中使用的参数不超过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
set设置位置参数
Linux set命令教程:如何优雅地设置和取消shell变量和选项(附实例详解和注意事项)_set设置的变量怎么取消-CSDN博客
Shell 变量可以分为两大类型:环境变和用户定义变量。环境变量用来定制您的 Shel的运行环境,保证Shell命令的正确执行。所有环境变量会传递给shell 的子进程。这些变量大多数在/etc/profile文件中初始化,而/etc/profile是在用户登录的时候执行的。
环境变量 | 说明 | 读写特性 |
$HOME | 当前用户的主目录 | 读写 |
$PATH | 以冒号分隔的用来搜索命令的目录列表 | 读写 |
$PS1 | 命令提示符通常是$字符,但在Bash中,您可以使用一些更复杂的值。例 如,字符串[u@\h\W]$就是一个流行的默认值,它给出用户名、机器名和 当前目录名,当然也包括一个$提示符 | 读写 |
$PS2 | 二级提示符,用来提示后续的输入,通常是>字符 | 读写 |
$IFS | 内部域分隔符,当shell 读取输入时,用来分隔单词的一组字符,它们通 常是空格、制表符和换行符 | 读写 |
修改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 中有两种方式可以完成命令替换,一种是反引号` `
,一种是$()
,使用方法如下:
- variable=`command`
- 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
不能删除只读变量,所以设置变量为“只读”时需要慎重,因为这个不可逆的操作
单双引号的使用
单引号
单引号是全引用,被单引号括起的内容不管是常量还是变量都不会发生替换。
也就是说单引号定义字符串所见即所得,将单引号内的内容输出,看到的是什么就会输出什么。
双引号
双引号是部分引用,被双引号括起的内容常量还是常量,变量则会发生替换,替换成变量内容。
变量的输入
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中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 | 如果文件可执行则结果为真 |
例:(第二章课后第6题《Linux高级程序设计》)
编写一个Bash 脚本程序,用for循环实现将当前目录下的所有.c文件移到指定的目录下,最后在显示器上显示指定目录下的文件和目录。
#! /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
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
break和continue
break跳出循环,continue跳出本次循环
exit语句
exit [n]