vim
插入模式下
/ 搜索内容
w 相当于Windows里的CTRL+S 及时保存
r 读取文件内容到当前光标位置 # : etc/passwd
x 保存退出=wq
X 对文件加密 可以把机密的文件加密,如密码表等
! 执行命令 # :!date
r! 把命令结果输出到光标位置
set nu 显示行号 setnonu 不显示行号
set ai 自动对齐
set ic 忽略大小写
set ff 文本格式转换 # :set ff=dos set ff=unix
set cul 下划线功能
set list 查看不可见字符
set ts=4 把tab变成4个空格键
set expandtab #配合上调set ts 使用
y 复制 # :2+5 y
p 粘贴
d 删除 # :7,15 d
% 全文 # :%d
s 搜索替换 # %s/哈哈/吧吧/g 吧全文的哈哈替换成baba
# : 1,5s/haha/baba/g 把haha替换成baba(g是整行的 haha 个替换成baba) 也可以把"/"换成其他符号如 "@" "#"
命令模式
ZQ 不保存退出 #等于 :q!
ZZ 保存退出 #等于 :wq
h j k l 上下左右 #3h 5l 可以带数字移动
H M L 吧当前页光标位置至于屏幕最上方行,中间行,最下方行
zt zz zb 吧光标处移动到屏幕顶端,重间,最后显示
G gg 5G 跳到最后一行 第一行 第五行
ctrl+f b u d翻半屏,全屏 #相当于pageup pagedown
x 删除当前光标处字符(一个) #之后还可按p粘贴(一个)
~ 转换大小写 #蛮实用的
dd yy 5dd 剪切当前行 复制当前行 剪切5行 P粘贴
/ 搜索 所搜之后 # N n 向上搜索 向下搜索
u U 撤销 撤销一次 U吧本行的所有操作全部撤销
ctrl+r 重做最后的撤销 # u完之后后悔了 ,用ctrl+r
di yi vi " ' { 剪切 复制 选中 " ' { 符号里的内容 '
ctrl+w s v同文件多窗口显示 #ctrl+w+上下左右切换窗口 ctrl+w+q或o退出
可视化模式 v V ctrl+v 面对字符 ,整行 面对块
如何把文件里的每一行前加上"#"符号?
答
#输入ctrl+v 进入可视化模式
#输入 G 跳到最后1行,选中第一行
#输入 I 切换至插入模式
#输入 #
#按 ESC 键
替换模式
R 开启替换模式,输入的字符将替换原有光标处的字符 # ESC即退出模式
#可以在家目录里创建一个 .vimrc的配置文件,把默认的vim配置放里
hedxdump查看二进制文本
od查看文本二进制或八进制十六进制 # od /data/haha.txt -t x1z
xxd查看二进制的文本
less 文本翻页 #有时候输出的命令结果跑的太快,可以用less来分页查看
head 查看文件前几行 默认10行 # -n15 前15行
tail 查看文件后几行 # -F 跟踪文件名 -f 跟踪文件(描述符)
# -n+3 从第三行开始显示
cut 取列 # -d 指定分隔符 -f 选列
# -c 选取字段 # cut -c2-15 /etc/passwd
# --complement 取反,取选定列相反的字段
paste 合并文件 #无卵用 -d指定分隔符
diff 比较文件不同 #卵用不大
cmp 比较文件二进制不同 #无卵用
wc 文本统计 # -l统计行 -w 统计单词 -c 统计字节 -m统计字符
sort 排序 # -n正常十进制数字排序
# -r反方向排序
# -R随即排序
# -f忽略大小写
# -u删除重复的行(经测试 -nu 与-u 有区别)
# -t -k #指定分隔符,选取第几列 #-t ' ' -k5 已空格为分隔符,选第5列
uniq 删除重复行
# -c 显示重复次数
# -d 只显示重复过的行
# -u 只显示没重复过的行
seq 100 | sort -R |head -1 #一百个数字取一个随机数
三剑客
grep -o 只显示匹配到的内容
-p 不做输出 (但可通过$?查询执行成功或失败)
-i 忽略大小写
-v 取反
-n 显示行号
-e 表示或关系 #cat /etc/passwd |grep -e bash -e root 显示包含root跟 bash的行
-w 匹配整个单词 # 除了数字,字母,下划线.其余都是单词的分界符
-A B C 匹配结果 前 后 重间 的行 # grep -A3 haha 包含haha下三行的行
-E 扩展模式 配皮扩展正则表达式
-R 递归,处理软链接 # -r 不处理软链接
-f 根据模式处理文件 # 可以 比较两个文件的相同行
#例子
[root@20:21:27 data]78# cat >2.log
12
23
hahah
345
[root@20:21:53 data]79# cat 1.log 2.log
123
234
345
hahaha
12
23
hahah
345
[root@20:21:58 data]80# grep -f 1.log 2.log
345
正则表达式
. 表示任意单个字符 #匹配的是字符,不是自己,所以汉字也可以被匹配
[] []表示包含 #和通配符相同
[^] 取[]里面的反 #和通配符相同 #grep [av]以不是av开头的行
- 出现0次或任意次 # hello l出现0次或任意次
. 任意字符串 #不是单个字符,不限制长度
? 单个字符出现0次或1次
+ 单个字符至少出现一次
{1,3} 匹配前面字符至少1次,至多三次
{} 匹配前面字符出现的次数# echo abcabcabc |grep 'c{1,3}'
# 筛选c出现过1次到三次的行
# echo abcabcabc |grep '(abc){3}'
# 筛选abc出现过三次的行
() 分组 # grep (haha) #吧haha作为一个分组
#%s@(haha)@\1er@g #在vim里吧 haha替换成hahaer
\b 词首或词尾 #<词首 > 词尾
^ 行首
$ 行尾
| 或 # (C|c)at cat 或Cat
# a|b
# cat|b cat或b
练习 正则表达式
1、显示/proc/meminfo文件中以大小s开头的行(要求:使用两种方法)
#cat /proc/meminfo |grep -i '^s.*'
#cat /proc/meminfo |grep -i s |sort |tail |head -9
2、显示/etc/passwd文件中不以/bin/bash结尾的行
#cat /etc/passwd |grep -v /bin/bash$
#cat /etc/passwd |grep -v 'bin/bash\b'
3、显示用户rpc默认的shell程序
#getent passwd rpc | cut -d ':' -f7
#/bin/bash
4、找出/etc/passwd中的两位或三位数 (找出系统用户的UID用数字来搜索)
#grep -Eo "[0-9]{2}|[0-9]{3}" /etc/passwd
#有瑕疵,四位数字的标识出来了三位
5、显示CentOS7的/etc/grub2.cfg文件中,至少以一个空白字符开头的且后面有非空白字
符的行
#cat /etc/grub2.cfg |grep ^[[:space:]] 只完成了一半
6、找出“netstat -tan”命令结果中以LISTEN后跟任意多个空白字符结尾的行
#netstat -tan |grep -o 'LISTEN[[:space:]]*'
7、显示CentOS7上所有UID小于1000以内的用户名和UID
#getent passwd |sort -t: -k3 -nr |tail -n+11 |cut -d : -f1,3 |tr ':' ' '
8、添加用户bash、testbash、basher、sh、nologin(其shell为/sbin/nologin),找出/etc/passwd用户名和shell同名的行
#?????
9、利用df和grep,取出磁盘各分区利用率,并从大到小排序
#df |grep ^/dev |tr -s ' ' '%' |cut -d % -f5|sort -nr |head -1
扩展
1、显示三个用户root、mage、wang的UID和默认shell
#getent passwd |grep -w -e ^root -e ^dachui -e ^tomcat |cut -d : -f3,7 |tr ':' ' '
2、找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
#
3、使用egrep取出/etc/rc.d/init.d/functions中其基名
#
4、使用egrep取出上面路径的目录名
#
5、统计last命令中以root登录的每个主机IP地址登录次数
#last |grep ^root.* |grep -v tty1 |tr -s ' '| cut -d ' ' -f3 |sort | uniq -c |sort -nr |head -1
6、利用扩展正则表达式分别表示0-9、10-99、100-199、200-249、250-255
# [1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]
# 判断一个IP是不是合法IP :
[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
7、显示ifconfig命令结果中所有IPv4地址
# ifconfig | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'
# 但吧其他的信息也匹配出来了子网掩码
8、将此字符串:welcome to magedu linux 中的每个字符去重并排序,重复次数多的排到前面
#
shell脚本
脚本须符合shebang机制 即 #!/bin/bash
大部分情况下,脚本需要加执行权行才可以运行 chmod+x XXX.sh
可以有四种方法运行脚本 #管道的方法,吧脚本传给bash
#吧文件路径添加到PATH变量里
#加执行权限,用绝对路径或相对路径发
#bash 加脚本 #不需要有执行权限
#source加脚本 #不需要执行权限
#bash 是相当于开启一个子进程执行脚本,source相当于在当前进程执行脚本
#相对来讲bash更安全一些,source容易修改当前的变量
#在修改配置文件的时候才建议使用source执行脚本
脚本的常见错误 #语法错误 语法出错后续行不会继续执行
#逻辑错误 系统判断不出逻辑错误
#命令错误 命令出错会继续执行后续行命令
可以用 bash -n 检查语法错误
#只是检查脚本中的语法,并不执行脚本
可以用 bash -x 检查命令执行过程 #逐行执行,并显示执行过程
#执行脚本并逐行显示执行的过程
变量可已存放命令比如
HAHA=date
[root@21:22:24 ~]145# $HAHA
Thu Apr 2 21:22:30 CST 2020
变量可以是很多种方式比如 : NAME=li
NAME=`whoami`
NAME=$USER
NAME=/etc/*
NAME="wang
li
zhao
qian"
$_存放的是前一个命令的最后一个参数
$-存放系统的关键字
$$是自己当前shell的PID
$PPID是父进程的ID
注意区别:
HAHA=`seq 5`
[root@13:27:59 ~]71# echo $HAHA
1 2 3 4 5
[root@13:28:04 ~]72# echo $"HAHA"
HAHA
[root@13:28:10 ~]73# echo "$HAHA"
1
2
3
4
5
注意区别:
[root@13:35:33 ~]77# QQQ=123
[root@13:35:41 ~]78# WWW=$QQQ
[root@13:35:48 ~]79# echo $QQQ
123
[root@13:35:52 ~]80# echo $WWW
123
[root@13:35:57 ~]81# QQQ=456
[root@13:36:05 ~]82# echo $QQQ
456
[root@13:36:07 ~]83# echo $WWW
123
[root@13:36:20 ~]86# unset QQQ
[root@13:36:32 ~]87# echo $QQQ
[root@13:36:33 ~]88# echo $WWW
123
为什么因为变量里的"="是赋值的意思不是等于号的意思,WWW的值赋值给了$QQQ也就是123,所以$QQQ改变凉了$WWW也是123,即使变量$QQQ被删除,也不会影响$WWW的值!
数字不可以作为变量名# 1=haha echo$1
下划线可以作为变量名称,下划线不可以作为主机名
横线可以作为主机名,横线不可以做为变量名
#echo $NAME_$AGE
#20
#echo ${NAME}_$AGE
#mage_20
普通变量无法在子进程或父进程使用 只能在当前终端使用 #脚本调用脚本也不继承
在自身进程里的变量优先级高于父进程的变量(如果重名的话)
export 可以声明环境变量 #
# export HAHA=baba
或者 # HAHA=baba # export HAHA
true 返回一个成功状态码
false返回一个错误状态码
set查看所有变量
set --清空位置变量
set -o 查看一些set的参数 #set -o xxx=on/off
set -e 当脚本中有一条命令出错后,就会停止执行脚本(只针对命令?)
set -u 如果脚本中存在没定义的变量,则不允许运行脚本
env即可查看所有的环境变量
readonly定义只读变量 exit当前窗口即可删除只读变量 只读变量只对当前窗口有效
位置变量 $0 $1 $2 $@ $*
#$0表示自身(命令和路径)
#$!表示第一个参数 $2表示第二个参数 $45表示第45个参数
#$@ 表示全部参数 #如果存在嵌套脚本,"$@"表示全部的独立参数
#$*表示全部参数 #如果存在嵌套脚本,"$*"表示把全部的参数当成一个参数
# $#显示本脚本参数的个数
注意:$@ $* 只在被双引号包起来的时候才会有差异
注意:如果想表示$45变量需要把45括起来,否则显示成$4加上字符5 #${45}才能表示出来
$?状态码 (只能查询上一条的执行结果)
#0表示上一条命令执行成功
#1-255表示执行失败
echo $?
0
print 相当于高级版本的echo #个人感觉用处不大
bash运算
let
$[] echo -e "\e[1;$[RANDOM%7+31]mhello world\e[0m" #实现随机颜色
$(())
expr # expr 2 \* 3 3 - 1 #只能取整数,且不支持浮点数
$( arg1 arg2 arg3 )
echo xxx |bc
与或非
与或非 true是1 false是0
$?里 1是上个命令执行失败 0是执行成功
变量互换
# i=10;j=20;k=$i;i=$j;j=$k;echo $i $j
i=20;j=10
# i=10;j=20:i=$[ij];j=[ij];i=[i^j];echo %i $j
i=20;j=
###异或三次可以实现两个值互换,就不需要第个那样的传统方法了
脚本
比较的命令:
test # test -a xxx
[] # [ $I -eq $Q ]
[[]] #支持正则表达式跟通配符 #[[ 条件 =~ 正则]] [[ 条件 == 通配符 ]]
#注意需要转义 # [[ $FILE =~ \.log$ ]] (匹配.log结尾的文件)
#注意是匹配的扩展正则表达式
数值判断: (只能用于数字判断)
# -eq 等于
# -ne 不等于
# -gt 大于
# -ge 大于等于
# -lt 小于
# -le 小于等于
# $SRT1 = $STR2 判断字符串是否相等(内容)
# $SRT1 != $STR2 判断字符串是否不等(内容)
字符串测试:
# = 是否字符串两边相等
# != 是否字符串两边不等
# == 用于[[]]匹配通配符模式
# =~ 用于[[]]匹配正则表达式
状态判断:
# -v 判断变量是否存在,(空也被判定为true)#(-R 也是判断变量是否存在,空则反馈false)
# -a 判断文件是否存在
# -b 判断是不是块文件
# -c 判断是不是字符文件
# -d 判断是不是文件夹
# -e 判断文件是否存在
# -f 判断是不是普通文件
# -z 字符串是空 (没定义或者是空值)
# -n 字符串非空
# -s 判断存在且大小大于0
# -h 判断是不是软链接
# -L 判断是不是软链接
# (判断软链接时,判断的是软链接指向的文件,如指向的件 是普通文件,则判定为普通文件)
权限判读:
# -r 判断文件是否有r权限
# -w 判断文件是否有w权限
# -x 判断文件是否有x权限
# [ -x "aa.txt" ] 判断aa.txt文件是不是又x权限
# 根据实际权限来判定,不见得是LL看见的文件权限
# () 开启一个子进程并执行()里的内容 #()里的变量不影响当前进程变量
#()可已继承父进程变量
# {} 不开启子进程,在当前进程执行{}里的内容 #{}里的变量影响当前进程变量
#(){}都可以将多个命令组合到一起执行,但结果不同
组合写法:[]
# -a 并且
# [ -f "$FILE" -a -x "$FILE" ] # $FILE文件是否是普通文件,并且具有执行权限 #条件全部满足就反馈true
# -o 或
# [ -f "$FILE" -o -x "$FILE" ] # $FILE文件是否是普通文件,或者$FILE是否具有执行权限 #满足一个条件就反馈true
# ! 取反
# ! [ -d /etc] echo $? 1
# [ ! -d /etc ] 两种写法都一样
# -a -o 只支持[]写法 [[]]不支持此写法
组合写法: && ||
# && 短路与 # id wang &> /dev/null && echo " $ID exits "
# || 短路或
比较[[]]的注意事项
在比较时[] | [[]] 内必须要有空格,如没有,则会被判定为变量赋值
为避免在[] | [[]] 是出现错误,建议在[] | [[]] 左侧变量加上""
# 在 [[ $"XX" == 通配符 ]] 右侧通配符加""只代表 ""里的内容本身,不带有其他含义
# 或者[[ "$XX" == 通配符]] 只想作为内容本身,也可以转义
判断一个IP是不是合法IP:
[[ "$IP" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
判断是不是一个数字:
[[ "$XXX" =~ [1]+$ ]]
判断是不是一个后缀:
[[ "$XX" == *.log ]] # == 用法似乎不需要转义
IF CASE
IF:
语法 if CMD1 ;then
CMD2
elif CMD3 ;then
CMD4
else CMD5
fi
case:
语法 case变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
*)
默认分支
;;
esac
例子:
#!/bin/bash
#alone test
read -p "are you alone? (input y/n)" ANS
case $ANS in
[Yy]|[Yy][Ee][Ss])
echo "you are alone"
;;
[Nn]|[Nn][Oo])
echo "you are not alone"
;;
*)
echo "wrong input"
esac
#!/bin/bash
#alone test
read -p "are you alone?(input y/n)" ANS
if [[ $ANS =~ [Yy]|[Yy][Ee][Ss] ]] ;then
echo "you are alone"
elif [[ $ANS =~ [Nn]|[Nn][Oo] ]] ;then
echo "you are not alone"
else echo "worng in put exit"
exit 100
fi
()跟{}的区别
#AA=dachui ; (echo $AA ;AA=xiaochui ; echo $AA); echo $AA 输出的结果?
dachui
xiaochui
dachui
#小括号默认开启了一个子进程,子进程的变量无法影响父进程
#()里的变量可已从父进程继承,无需定义成环境变量 #小括号的特性
#AA=dachui ; { echo $AA ;AA=xiaochui ; echo $AA; }; echo $AA输出的结果?
dachui
xiaochui
xiaochui
#{}的使用方法是 {}里的内容与括号本身用空格隔开,且最后结束前加; 即{ XX XX; }
#{}不开启子进程,花括号里的变量影响当前进程的变量
shell脚本里如果定义的一个变量是命令,千万记得加``不然不生效
read
read 可以给变量赋值 如果没输入变量名称,默认把输入的内容存入$REPLA变量里
# read
haha
echo $REPLA
haha
# read AA
wawa
echo $AA
wawa
# read可以一次给多个变量赋值
# read a b
xx yy
echo $a $b
XX YY
read -p 不换行并且加提示 #很常用
read -s 静默输入 (长用于密码)
read -t timeout时间 #read -t 35 #35秒不进行输入则超时
read -n 指定输入的字符长度
配置文件
配置文件分为全局配置和个人配置,全局配置都放在/etc/目录下,个人配置方在~目录下
已下几个文件可以影响bash的配置
全局配置:
/etc/profile
/etc/profile.d/*.sh #即/etc/profile.d/任何已.sh结尾的文件
/etc/bashrc
个人配置:
~/.bash_profile #登入时执行
~/.bashrc #登入时执行
~/.bash_logout #退出时执行此脚本
通常来讲建议吧配置文件方在/etc/profile.d/文件夹下自建一个.sh的文件,此法不修改系统的配置文件,而且无论su还是su - 都需要读取此文件,此文件不用及删非常方便
profile与bashrc的区别:
profile:存放环境变量跟脚本
bashrc:存放普通变量跟别名
#Ubutun的PS1变量建议方在profile文件中
0-9 ↩︎
浙公网安备 33010602011771号