shell脚本编程学习笔记

前言

最近在学shell脚本。这玩意我觉得不好学,语法奇葩,命令繁多,而且不够严谨。

比如四则运算表达式,$(()),$[],expr a + b ,let xxx,有这四种,expr 后的运算符号两边得有空格;

再比如if条件判断中的条件,可以写成 test xxx,或者[ xxx ],或者[[ xxx ]],或者类c风格 ((2<3)),你说你搞这么多形式干嘛呢,这不是增加学习成本吗?

再比如:

root@aliyun:~# test 1 -eq 1 -a 2 -eq 2;echo $?
0

root@aliyun:~# test 1 -eq 1 -a test 2 -eq 2;echo $?
-bash: test: too many arguments
2

root@aliyun:~# test 1 -eq 1 && 2 -eq 2;echo $?
2: command not found
127

root@aliyun:~# test 1 -eq 1 && test 2 -eq 2;echo $?
0

用-a后面不能再跟test,用&&后面还必须要加上test,这不是扯犊子么?

唉,先学点基础的吧,以后复杂的直接用python来代替。

Vim文本编辑器

1、插入文本操作

快捷键功能描述
i 在当前光标所在位置插入随后输入的文本,光标后的文本相应向右移动
I 在光标所在行的行首插入随后输入的文本,行首是该行的第一个非空白字符,相当于光标移动到行首执行 i 命令
o 在光标所在行的下面插入新的一行。光标停在空行首,等待输入文本
O(大写) 在光标所在行的上面插入新的一行。光标停在空行的行首,等待输入文本
a 在当前光标所在位置之后插入随后输入的文本
A 在光标所在行的行尾插入随后输入的文本,相当于光标移动到行尾再执行 a 命令

 

2、查找文本 

快捷键功能描述
/abc 从光标所在位置向前查找字符串 abc
/^abc 查找以 abc 为行首的行
/abc$ 查找以 abc 为行尾的行
?abc 从光标所在位置向后查找字符串 abc
n 向同一方向重复上次的查找指令
N 向相反方向重复上次的查找指定

 

注意:如果在字符串中出现特殊符号,则需要加上转义字符 "\"。常见的特殊符号有 \、*、?、$ 等。如果出现这些字符,例如,要查找字符串 "10$",则需要在命令模式中输入 "/10\$"。

 3、文本替换

快捷键功能描述
r 替换光标所在位置的字符
R 从光标所在位置开始替换字符,其输入内容会覆盖掉后面等长的文本内容,按“Esc”可以结束
:s/a1/a2/g 将当前光标所在行中的所有 a1 用 a2 替换
:n1,n2s/a1/a2/g 将文件中 n1 到 n2 行中所有 a1 都用 a2 替换

:%s/a1/a2/g

或者:1,$s/a1/a2/g

将文件中所有的 a1 都用 a2 替换

4、删除文本

快捷键功能描述
x 删除光标所在位置的字符
dd 删除光标所在行
ndd 删除当前行(包括此行)后 n 行文本
dG 删除光标所在行一直到文件末尾的所有内容
D 删除光标位置到行尾的内容
:a1,a2d 函数从 a1 行到 a2 行的文本内容

5、复制文本

快捷键功能描述
p 将剪贴板中的内容粘贴到光标后
P(大写) 将剪贴板中的内容粘贴到光标前
v 上下移动光标选中文本后按y复制到剪切板,再p粘贴
yy 将光标所在行复制到剪贴板,此命令前可以加数字 n,可复制多行
Y 复制光标所在行

6、保存文本

命令功能描述
:wq 保存并退出 Vim 编辑器
:wq! 保存并强制退出 Vim 编辑器
:q 不保存就退出 Vim 编辑器
:q! 不保存,且强制退出 Vim 编辑器
:w 保存但是不退出 Vim 编辑器
:w! 强制保存文本
:w filename 另存到 filename 文件
x! 保存文本,并退出 Vim 编辑器,更通用的一个 vim 命令
ZZ 直接退出 Vim 编辑器

注意:"w!" 和 "wq!" 等类似的指令,通常用于对文件没有写权限的时候(显示 readonly,如图 12 所示),但如果你是文件的所有者或者 root 用户,就可以强制执行。

7、其他快捷键

J:将当前行与下一行用空格合并连接成一行

u:撤销操作

关于用户

创建用户:useradd -r -m -s /bin/bash username      创建系统用户并生成家目录

 

删除用户:userdel -r username    -r 选项表示在删除用户的同时删除用户的家目录。

 

给普通用户wangyi添加root权限:usermod -a -G sudo wangyi  

直接给wangyi添加附加组sudo,sudo组的权限通过visudo可以看到,如下,跟root用户一样。不想每次sudo都输入密码可以在sudo那里最后一个ALL前面加上NOPASSWD:

注意:这个visudo默认用nano编辑器打开,保存用ctrl+o,然后回车,再ctrl+x

 

用户组

查看用户组:/etc/group

 用:隔成4个字段,每个字段的含义为:

1、组名

也就是是用户组的名称,由字母或数字构成。同 /etc/passwd 中的用户名一样,组名也不能重复。

2、组密码

和 /etc/passwd 文件一样,这里的 "x" 仅仅是密码标识,真正加密后的组密码默认保存在 /etc/gshadow 文件中。
不过,用户设置密码是为了验证用户的身份,那用户组设置密码是用来做什么的呢?用户组密码主要是用来指定组管理员的,由于系统中的账号可能会非常多,root 用户可能没有时间进行用户的组调整,这时可以给用户组指定组管理员,如果有用户需要加入或退出某用户组,可以由该组的组管理员替代 root 进行管理。但是这项功能目前很少使用,我们也很少设置组密码。如果需要赋予某用户调整某个用户组的权限,则可以使用 sudo 命令代替。

3、组ID (GID)

就是群组的 ID 号,Linux 系统就是通过 GID 来区分用户组的,同用户名一样,组名也只是为了便于管理员记忆。
这里的组 GID 与 /etc/passwd 文件中第 4 个字段的 GID 相对应,实际上,/etc/passwd 文件中使用 GID 对应的群组名,就是通过此文件对应得到的。

4、组中的用户

此字段列出每个群组包含的所有用户。需要注意的是,如果该用户组是这个用户的初始组,则该用户不会写入这个字段,可以这么理解,该字段显示的用户都是这个用户组的附加用户。
举个例子,lamp 组的组信息为 "lamp:x:502:",可以看到,第四个字段没有写入 lamp 用户,因为 lamp 组是 lamp 用户的初始组。如果要查询这些用户的初始组,则需要先到 /etc/passwd 文件中查看 GID(第四个字段),然后到 /etc/group 文件中比对组名。
每个用户都可以加入多个附加组,但是只能属于一个初始组。所以我们在实际工作中,如果需要把用户加入其他组,则需要以附加组的形式添加。例如,我们想让 lamp 也加入 root 这个群组,那么只需要在第一行的最后一个字段加入 lamp,即 root:x:0:lamp 就可以了。

 

一般情况下,用户的初始组就是在建立用户的同时建立的和用户名相同的组。
对于/etc/passwd、/etc/shadow、/etc/group,它们之间的关系可以这样理解,即先在 /etc/group 文件中查询用户组的 GID 和组名;然后在 /etc/passwd 文件中查找该 GID 是哪个用户的初始组,同时提取这个用户的用户名和 UID;最后通过 UID 到 /etc/shadow 文件中提取和这个用户相匹配的密码。

运算符

注意:(( )) 只能进行整数运算,不能对小数(浮点数)或者字符串进行运算。bc 命令可以用于小数运算。

和双小括号 (( )) 一样,let 命令也只能进行整数运算,不能对小数(浮点数)或者字符串进行运算。 

注意:(( )) 只能进行整数运算,不能对小数(浮点数)或者字符串进行运算。后续讲到的 bc 命令可以用于小数运算。

root@aliyun:~/shell/while# a=2
root@aliyun:~/shell/while# let a+=1
root@aliyun:~/shell/while# echo $a
3

oot@aliyun:~/shell/while# let a+=1
root@aliyun:~/shell/while# echo $a
3

 

循环控制语句

案例1:

 

 

案例2:

 

 

案例3:

 

 

案例4:

 

 

案例5:

 

 

案例5:

 

 

案例6:

 

案例7:

 

 

 

 

 案例8:

 

 案例9:

 执行:

 

案例10:

 

数组

shell中没有限制数组大小。

定义数组:

array=(1 2 3 "hehe")

arr[1]=1

arr=(`ls`)

arr=($(cat file))  将文件中的每一行或者空格隔开的内容作为数组的元素

a=1;arr[$a]=11  数组下标也可以是变量的值,若arr[1]之前存在,则直接修改arr[1]

获取数组:

echo ${arr[1]}  获取数组的第二个元素

echo ${arr[@]} 获取数组所有元素,@等价于*

echo ${#arr[@]}   获取数组元素的个数

echo ${arr[*]:1:3}  从第二个元素开始获取3个数组元素

echo ${!arr[@]}  获取所有元素的索引下标

declare -a 获取普通数组信息

关联数组:

下标可以为字符串:(当然也可以是整数)

定义前要声明:declare -A 关联数组名

也可以:asso_arr=([name]=wangyi [age]=18)

获取:

类似于python中的字典。

 

Linux的小命令

1、dirname 获取目录

2、basename 取出文件

 

 3、去除变量的部分内容

#从左去除,%从右,##去除所有匹配到的,%%一样。

 

 4、未得其名,却得其实

直接在root账户下,在用户wangyi的家目录下创建文件

 

 5、cat <<EOF 展示输出

 

 cat > 3.txt <<EOF  输出重定向,向3.txt文件覆盖写入数据  >>3.txt 是追加写

 

 或者直接用这种方式创建文件并写入数据:

 

注意,在脚本中,要用<<-EOF消除EOF命令前的制表符,不然会报错

 

 

 

函数

1、环境变量

将函数添加到用户家目录下的.bashrc中,这样其他用户不可调用

 

若要全局生效,则在etc/bashrc里面定义函数。

2、用例

简单的登录判断:

 

 login函数也可换成这样:

 

 

 注意:字符串判断==两边留空格并用引号引起来。

 

正则表达式

元字符:在正则中,具有特殊意义的专用字符,如: 星号(*)、加号(+)等

前导字符:元字符前面的字符叫前导字符

 

 

注意: 其中 + ? | ()这几个扩展字符用grep时要加-E。

 

 

 

Liunx文本处理三剑客

 1、grep (global regular expressions print)

常用选项:

-i: 不区分大小写

-v: 查找不包含指定内容的行,反向选择

-w: 按单词搜索

-o: 打印匹配关键字

-c: 统计匹配到的行数

-n: 显示行号

-r: 逐层遍历目录查找

-A: 显示匹配行及后面多少行

-B: 显示匹配行及前面多少行

-C: 显示匹配行前后多少行

-l:只列出匹配的文件名

-L:列出不匹配的文件名

-e: 使用正则匹配

-E:使用扩展正则匹配

^key:以关键字开头

key$:以关键字结尾

^$:匹配空行

--color=auto :可以将找到的关键词部分加上颜色的显示

 

举例:

# grep -i root passwd				忽略大小写匹配包含root的行
# grep -w ftp passwd 				精确匹配ftp单词
# grep -w hello passwd 				精确匹配hello单词;自己添加包含hello的行到文件
# grep -wo ftp passwd 				打印匹配到的关键字ftp
# grep -n root passwd 				打印匹配到root关键字的行好
# grep -ni root passwd 				忽略大小写匹配统计包含关键字root的行
# grep -nic root passwd				忽略大小写匹配统计包含关键字root的行数
# grep -i ^root passwd 				忽略大小写匹配以root开头的行
# grep bash$ passwd 				匹配以bash结尾的行
# grep -n ^$ passwd 				匹配空行并打印行号
# grep ^# /etc/vsftpd/vsftpd.conf		匹配以#号开头的行
# grep -v ^# /etc/vsftpd/vsftpd.conf	    匹配不以#号开头的行
# grep -A 5 mail passwd 			匹配包含mail关键字及其后5行
# grep -B 5 mail passwd 			匹配包含mail关键字及其前5行
# grep -C 5 mail passwd 			匹配包含mail关键字及其前后5行

2、sed

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

未完待续。。。

posted @ 2020-08-14 23:16  天青色wy  阅读(346)  评论(0编辑  收藏  举报