知识点
如何执行脚本
在脚本中指定解释器
可以在文件第一行 ,之前不能有回车
#! 解释器路径
例子
vi shell_1
#! /usr/local/miniconda3/bin/python3.7
print("这是在文件开始指定了python3解释器的文件")
执行这个脚本文件
./shell_1
sh: ./shell_1: Permission denied
说明权限不够
分配给他权限
chmod +x ./shell_1
或者直接
chmod 777 shell_1
再次执行
./shell_1
这是在文件开始指定了python3解释器的文件
绝对路径执行
/home/shellStudy/shell_1
这是在文件开始指定了python3解释器的文件
直接在执行时指定解释器
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
python3 shell_1
这是在文件开始指定了python3解释器的文件
linux 自带的解释器 /bin/bash
sh-4.2# /bin/bash
(base) [root@20351ba90c2a shellStudy]#
接下来,来学习/bin/bash 的 shell 语法
为什么执行要写作 ./ file
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,
直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,
要用 ./test.sh 告诉系统说,就在当前目录找。
Bourne Again Shell(/bin/bash) 的语法
变量
定义变量
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
sh-4.2# var1="what are you doing now?"
sh-4.2#
没有报错说明定义成功
变量可以被重复定义
使用定义过的变量
使用变量前需要在变量之前加上${ var }
外边的 大括号 最好都加上。这样可以防止一些特殊情况的出现
当然了 $var 后边加空格分开变量,也是可以的
sh-4.2# echo $var1
what are you doing now?
简单循环中的变量
for skill in pyhton C C++ Java; do
echo "I am good at $skill language"
done
I am good at pyhton language
I am good at C language
I am good at C++ language
I am good at Java language
只读变量
当定义了一个变量以后,可以使用readonly var 来将变量变成只读变量
readonly var
删除变量
unset var
变量类型
运行shell时,会同时存在三种变量:
- 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
var1="this is 局部变量"
- 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
java
输出 用法:java [options] <主类> [args...]
- shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
字符串变量
单引号字符串
str=‘this is a string’
单引号字符串的限制:
单引号里的任何字符都会原样输出,
单引号字符串中的变量是无效的;
单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
双引号字符串:
双引号里可以有变量
双引号里可以出现转义字符
当字符串中 嵌入 变量时,单双引号的差别
sh-4.2# var1="早上"
sh-4.2# var10="$var1 吃饼"
sh-4.2# var11='$var1 喝茶'
sh-4.2# echo $var10 $var11
早上 吃饼
$var1 喝茶
获取字符长度
${#varname}
sh-4.2# echo ${#var1}
2
for tempvar in asasas asasasasas qwqwqw ;do
echo ${#tempvar};
done;
6
10
6
提取字符串子串
${var: 起始位置 : 截取多少个字符 }
var1="今天早上出去吃了豆浆油条"
sh-4.2# varson=${var1:0:3}
sh-4.2# echo $varson
今天早
从0开始截取4个字符
sh-4.2# varson=${var1:0:4}
sh-4.2# echo $varson
今天早上
从1开始截取4个字符
sh-4.2# varson=${var1:1:4}
sh-4.2# echo $varson
天早上出
参数传递
单个获取参数
在执行脚本的时候我们通常会向脚本内部传入变量
传入后,可以在脚本内部使用 $n 来得到传入参数 n
$0代表当前执行的文件名称
参数方法
$# 传递到脚本的参数个数
$@ 以"$1" "$2" … "$n" 的形式输出所有参数。
$* 以一个单字符串显示所有向脚本传递的参数。
$$ 代表当前进程的pid
$! 最近一个后台进程的pid
$* 与 $@ 区别:
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,
则 " * " 等价于 “1 2 3”(传递了一个参数)
,而 “@” 等价于 “1” “2” “3”(传递了三个参数)。
循环遍历输出参数
vi shell_get_para…sh
for var1 in $@ ; do
echo $var1 ;
done ;
运行输出
./shell_get_para.sh 参数1 参数2
参数1
参数2
数组
创建数组与访问数组
shell 只支持1维数组
创建方法1 listname=(var1 var2 … var3) 变量之间使用空格间隔
list1=( 1 'a' 'b' 'good' )
根据下表创建数组,下标可以不是连续的,shell中的数组不会进行边界检查,当下标不存在变量的时候,会直接返回空
my_array[0]="a0"
my_array[3]="a3"
输出数组长度
echo ${#my_array}
输出数组变量内容
echo ${my_array[@]}
a0 a3
注意直接访问数组,只会返回数组的第一个元素
echo ${my_array}
a0
遍历数组中的变量
for onevar in ${list1[*]} ;do echo $onevar ; done;
运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,
例如 awk 和 expr,expr 最常用。
val=`expr 2 + 2`
echo $val
4
表达式和运算符之间要有空格,
例如 2+2 是不对的,必须写成 2 + 2,
这与我们熟悉的大多数编程语言不一样。
完整的表达式要被 ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。
a0=10 ; b0=20;
加减
echo `expr $a0 + $b0`
30
乘法 乘法运算符是 \* 运算符两侧的操作数必须要有,k'm
echo `expr $a0 \* $b0`
200
除法操作
echo `expr $a0 / $b0`
0
取余操作
echo `expr $a0 % $b0`
0
a0=$b0
echo $a0
20
比较符号以及逻辑符号
-eq 相等
-ne 不相等
-gt > 于号
-gt是大于
-lt是小于
-eq是等于
-ne是不等于
-ge是大于等于
-le是小于等于
!非
-o 或
-a 与
&& 与
|| 或
检测文件
-r file 检测文件是否可读,如果是,则返回 true。
-w file 检测文件是否可写,如果是,则返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。
特殊命令
echo 命令
echo "\"It is a test\""
echo 重定向到 环境变量 配置文件 /etc/profile
//将某个目录添加到 环境变量 里来
echo " export PATH=$PATH:/usr/local/miniconda3/bin " >> /etc/profile
read 命令
read name1
asd
echo $name1
asd
printf 命令
./shell_printf.sh 文件内容如下
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
./shell_printf.sh
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99
test命令
用来检测命令
if test -e ./bash
-e 文件名 如果文件存在则为真
控制结构
if
then
...
elif
...
else
.....
fi
写做一行
if [ 20 -eq 20 ] ;then echo "yes" ;fi
yes
假设目录下存在 shell_1 ,不存在 shell_2
if test -e shell_1 ;then echo "yes"; else echo "no this file " ;fi
yes
if test -e shell_2 ; then echo "yes" ; else echo "no this file " ;fi
no this file
if 后边的条件如果不使用test命令,必须要 if 空格 [space 条件 space];then
fi
if [ $i<10 ]
循环结构
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
输出当前目录下的文件的目录
for var in `cd .. && ls `; do echo $var; done; c
while 循环 (( condition )) 必须是双括号
循环输出 i = 1,2,3,4,5
方法一
i=1; while(( $i<=5 )); do echo "$i"; i=` expr $i + 1 `; done
方法而
i=1;while(($i<=5));do echo $i ; let i=i+1 ;done
死循环
i=0
while :
do
echo $i
let i=i+1
if [ $i>3 ]
then
break
fi
done
使用if 跳出while循环
i=0;
while true;
do let i=i+1 ;
echo $i ;
if [ $i -eq 3 ];
then break;
fi;
done