egrep,linux环境配置及脚本,vim编辑器(第6天)

1:egrep及扩展的正则表达式
egrep相当于grep -E
egrep [OPTIONS] PATTERN [FILE...]

扩展正则表达式的元字符(基本和基本正则一样):
字符匹配:
      .
      []
      [^]

次数匹配:
      *
      ?  表示0或1次;
      +  表示1次或多次;
      {m}  表示匹配m次;
      {m,n}  表示至少m,至多n次;

位置锚定:
      ^
      $
      \<, \b
      \>, \b

分组:
      ()
      后向引用:\1, \2, ...

或者:
      a|b  表示a或者b

练习:
1、显示当前系统root、centos或user1用户的默认shell和UID;
# grep -E '^(root|centos|user1)\>' /etc/passwd | cut -d: -f1,3,7

2、找出/etc/rc.d/init.d/functions文件(centos6)中某单词后面跟一个小括号的行;
# grep -E  "^[_[:alpha:]]+\(\)" /etc/rc.d/init.d/functions

3、使用echo输出一绝对路径,使用egrep取出其基名;
# echo "/mnt/sdc" | grep -E -o "[^/]+/?$" | cut -d"/" -f1

进一步地:使用egrep取出路径的目录名,类似于dirname命令的结果;
# echo  /mnt/usb/docker.doc | grep -E -o ""
# echo  /mnt/usb/ | grep -E -o ""

4、找出ifconfig命令结果中1-255之间的数值;

5、找出ifconfig命令结果中的IP地址;

2:fgrep不支持正则表达式搜索;

3:bash的基础特性(4)
变量类型:不同的类型有不同的数据存储格式、不同的存储空间大小、不同的参与运算种类
变量类型有数值型和字符型,数值型分为整型和浮点型

强类型:定义变量时必须指定类型、参与运算必须符合类型要求;调用未声明变量会产生错误;
弱类型:无须指定类型,默认均为字符型;参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用;

bash中的变量的种类:
根据变量的生效范围等标准:
      本地变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效;
      环境变量:生效范围为当前shell进程及其子进程;
      局部变量:生效范围为当前shell进程中某代码片断(通常指函数);
      位置变量:$1, $2, ...来表示,用于让脚本在脚本代码中调用,通过命令行传递给它的参数;
      特殊变量:$?(命令执行结果的状态), $0(命令本身), $*, $@, $#

本地变量:
变量赋值:name='value'
可以使用引用:
value:
(1) 可以是直接字串; name="username"
(2) 变量引用:name="$username"
(3) 命令引用:name=`COMMAND`相当于name=$(COMMAND)
变量引用:${name}, $name
"":弱引用,其中的变量引用会被替换为变量值;
'':强引用,其中的变量引用不会被替换为变量值,而保持原字符串;
显示已定义的所有变量
      set
销毁变量:
      unset name
举个例子:定义一个变量保存当前日期
current_date=`date "+%F"`
echo $current_date

环境变量:
环境变量声明、赋值有如下2种方式:
      export name=VALUE
      declare -x name=VALUE
变量引用:$name, ${name}
显示所有环境变量有如下3个命令:
      export
      env
      printenv
销毁变量:
      unset name
bash有许多内建的环境变量:PATH, SHELL, UID, HISTSIZE, HOME, PWD, OLD, HISTFILE, PS1

变量命名法则:
1、不能使程序中的保留字:例如if, for;
2、只能使用数字、字母及下划线,且不能以数字开头;
3、见名知义,

定义只读变量的2种方式:
readonly name
declare -r name

位置变量:
在脚本代码中调用通过命令行传递给脚本的参数;
$1, $2, ...:对应调用第1、第2等参数;shift [n]
$0: 命令本身;
$*: 传递给脚本的所有参数;
$@: 传递给脚本的所有参数;
$#: 传递给脚本的参数的个数;

示例:判断给出的文件的行数
#!/bin/bash
linecount="$(wc -l $1| cut -d' ' -f1)"
echo "$1 has $linecount lines."


bash的配置文件: 按生效范围划分,存在两类: 全局配置:在etc目录下 /etc/profile /etc/profile.d/*.sh /etc/bashrc 个人配置:在个人家目录下 ~/.bash_profile ~/.bashrc

按功能划分,存在两类: profile类:为交互式登录的shell提供配置 全局:/etc/profile, /etc/profile.d/*.sh 个人:~/.bash_profile
功用:(1) 用于定义环境变量;(2) 用于运行命令或脚本;
bashrc类:为非交互式登录的shell提供配置 全局:/etc/bashrc
个人:~/.bashrc
功用:(1) 用于定义本地变量;(2)用于 定义命令别名;

shell登录分为交互式登录和非交互式登录:
交互式登录:
直接通过终端输入账号密码登录;
使用“su - UserName”或“su -l UserName”切换的用户
/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
非交互式登录:

su UserName
图形界面下打开的终端
执行脚本
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh


 编辑配置文件定义的新配置的生效方式:
(1) 重新启动shell进程;
(2) 使用source或.命令进程;

 问题:
1、定义对所有用户都生效的别名?
编辑/etc/bashrc加入别名即可 

2、让所有用户的PATH环境变量的值多出一个路径,例如多如/usr/local/apache2/bin
编辑/etc/profile文件加入如下代码之一:
export PATH="$PATH:/usr/local/apache2/bin"
declare -x PATH="$PATH:/usr/local/apache2/bin"

 3、让管理员的PATH环境变量的值多出一个路径,例如多如/usr/local/apache2/bin
编辑管理员的.bash_profile 文件加入如下代码之一:
export PATH="$PATH:/usr/local/apache2/bin"
declare -x PATH="$PATH:/usr/local/apache2/bin"

bash中的算术运算
+, -, *, /, %, **

实现算术运算有如下4种方法:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...)  例如 sum=$(expr $num1 + $num2)  不建议使用


bash有内建的随机数生成器:$RANDOM  例如 echo $[$RANDOM%60+1]

增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=1

自增,自减:
let var+=1
let var++
let var-=1
let var--

练习1:写一个脚本
计算/etc/passwd文件中的第10个用户和第20用户的ID之和;
#!/bin/bash
user1_id=`head -10 /etc/passwd | tail -1 | cut -d: -f3`
user2_id=`head -20 /etc/passwd | tail -1 | cut -d: -f3`
echo $[$user1_id+$user2_id]

练习2:写一个脚本
传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和;
#!/bin/bash
space_line1=`grep "^[[:space:]]*$" $1 | wc -l`
space_line2=`grep "^[[:space:]]*$" $2 | wc -l`
echo $[$space_line1+$space_line2]

练习3:统计/etc, /var, /usr目录共有多少个一级子目录和文件;
#!/bin/bash
etc_sum=`ls /etc | wc -l`
var_sum=`ls /var | wc -l`
usr_sum=`ls /usr | wc -l`
echo $[$etc_sum+$var_sum+$usr_sum]

条件测试:
判断某需求是否满足,需要由测试机制来实现;
Note: 专用的测试表达式需要由测试命令辅助完成测试过程;

测试命令:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
Note: EXPRESSION前后必须有空白字符;

bash的测试类型,有3种:
数值测试:
      -gt: 是否大于;
      -ge: 是否大于等于;
      -eq: 是否等于;
      -ne: 是否不等于;
      -lt: 是否小于;
      -le: 是否小于等于;
字符串测试:
      ==:是否等于;
      >: 是否大于;
      <: 是否小于;
      !=: 是否不等于;
      =~: 左侧字符串是否能够被右侧的PATTERN所匹配;Note: 此表达式一般用于[[  ]]中;
      -z "STRING":测试字符串是否为空,空则为真,不空则为假;
      -n "STRING":测试字符串是否不空,不空则为真,空则为假;
      Note:用于字符串比较时的用到的操作数都应该使用引号;
文件测试:
      存在性测试
      -a FILE   文件存在性测试,存在为真,否则为假;
      -e FILE   文件存在性测试,存在为真,否则为假;
      存在性及类别测试
      -b FILE   是否存在且为块设备文件;
      -c FILE   是否存在且为字符设备文件;
      -d FILE   是否存在且为目录文件;
      -f FILE  是否存在且为普通文件;
      -h FILE 或 -L FILE  存在且为符号链接文件;
      -p FILE   是否存在且为命名管道文件;
      -S FILE    是否存在且为套接字文件;
      文件权限测试:
      -r FILE   是否存在且可读,执行脚本的用户对该文件是否可读
      -w FILE   是否存在且可写
      -x FILE   是否存在且可执行
      文件特殊权限测试:
      -g FILE:是否存在且拥有sgid权限;
      -u FILE:是否存在且拥有suid权限;
      -k FILE:是否存在且拥有sticky权限;
      文件大小测试:
      -s FILE: 是否存且非空;
      文件是否打开:
      -t fd   fd表示文件描述符是否已经打开且与某终端相关


      -N FILE   文件自从上一次被读取之后是否被修改过;
      -O FILE   当前有效用户是否为文件属主;
      -G FILE   当前有效用户是否为文件属组;

      双目测试:
      FILE1 -ef FILE2   FILE1与FILE2是否指向同一个设备上的相同inode
      FILE1 -nt FILE2   FILE1是否新于FILE2;
      FILE1 -ot FILE2   FILE1是否旧于FILE2;

组合测试条件:
逻辑运算:
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
例子  [ -e FILE ] && [ -r FILE ]

第二种方式:
EXPRESSION1 -a EXPRESSION2
EXPRESSION1 -o EXPRESSION2
! EXPRESSION
必须使用测试命令进行;

# [ -z "$hostName" -o "$hostName"=="localhost.localdomain" ] && hostname www.magedu.com
# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab


bash自定义退出状态码
exit [n]:自定义退出状态码;
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字;
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码;
练习:写一个脚本
接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出; 如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数;
#!/bin/bash
[ $# -lt 1 ]  &&  echo "at least provite one arg" && exit 1 || echo "`grep "^[[:space:]]*$" $1 |  wc -l`"

4:vim编辑器
vi: Visual Interface,文本编辑器
VIM - Vi IMproved

基本模式有3个:
编辑模式,也称为命令模式
输入模式
末行模式:内置的命令行接口

打开文件:
# vim [OPTION]... FILE...
vim +# FILE  打开文件后,直接让光标处于第#行的行首;
vim +/PATTERN FILE 打开文件后,让光标处于第一个被PATTERN匹配到的行的行首;

模式转换:
编辑模式 --> 输入模式
i: insert, 在光标所在处输入;
a: append, 在光标所在处后面输入;
o: 在当前光标所在行的下方打开一个新行;
I:在当前光标所在行的行首输入;
A:在当前光标所在行的行尾输入;
O:在当前光标所在行的上方打开一个新行;
c
C

输入模式 --> 编辑模式
              ESC

编辑模式 --> 末行模式
              :

末行模式 --> 编辑模式
              ESC

关闭文件:
:q 退出
:q! 强制退出,丢弃做出的修改;
:wq 保存退出
:x 保存退出
:w /PATH/TO/SOMEWHERE
命令模式下ZZ也可以保存退出

光标跳转:包括字符间跳转,单词间跳转,行首行尾跳转,行间移动,句间移动,段落间移动等等
字符间跳转:
h, j, k, l
h: 表示左
l:  表示右
j:  表示下
k: 表示上
#k   表示向上移动#行;

单词间跳转:
w:下一个单词的词首
e: 当前或下一个单词的词尾
b:当前或前一个单词的词首
#COMMAND  表示由#指定一次跳转的单词数

行首行尾跳转:
^: 跳转至行首的第一个非空白字符;
0: 跳转至行首;
$: 跳转至行尾;

行间移动:
#G:跳转至由#指定的行;
G:最后一行;
1G, gg: 第一行;

句间移动:
)
(

段落间移动:
}
{

vim的编辑命令:包括字符编辑,删除命令粘贴命令,复制命令,改变命令
字符编辑:
x: 删除光标处的字符;
#x: 删除光标处起始的#个字符;
xp: 交换光标所在处的字符及其后面字符的位置;

删除命令:
d: 删除命令,可结合光标跳转字符,实现范围删除;
d$: 删除
d^:
d0:
dw
de
db
#dw  表示删除#个单词
dd: 删除光标所在的行;
#dd:多行删除;

粘贴命令(p, put, paste):
p:缓冲区存的如果为整行,则粘贴当前光标所在行的下方;否则,则粘贴至当前光标所在处的后面;小写p
P:缓冲区存的如果为整行,则粘贴当前光标所在行的上方;否则,则粘贴至当前光标所在处的前面;大写P

复制命令(y, yank):y: 复制,工作行为相似于d命令;
y$
y0
y^
ye
yw
yb
#ye
yy:复制行
#yy: 复制多行;

改变命令(c, change)  c: 修改
c命令执行之后,从编辑模式 转到 输入模式
c$
c^
c0
cw
ce
cb
#ce
cc:删除并输入新内容
#cc:

其他编辑操作:(可视化模式,撤消此前的编辑,撤消此前的撤消,重复前一个编辑操作)
可视化模式:
v: 按字符选定
V:按行行定
Note:经常结合编辑命令;d, c, y等使用

撤消此前的编辑:
u(undo):撤消此前的操作;
#u: 撤消指定次数的操作;

撤消此前的撤消:
Ctrl+r

重复前一个编辑操作:
.  点号

翻屏操作:和less命令一样
Ctrl+f: 向文件尾部翻一屏;
Ctrl+b: 向文件首部翻一屏;
Ctrl+d: 向文件尾部翻半屏;
Ctrl+u:向文件首部翻半屏;

vim自带的练习教程:
vimtutor命令可以打开vim教程

vim中的末行模式:内建的命令行接口 (地址界定,查找,查找并替换)
(1) 地址定界
:start_pos,end_pos  其中start_pos表示起始位置,end_pos表示末尾位置
例子如下:
#  表示具体第#行,例如2表示第2行;
#,#  表示从左侧#表示行起始,到右侧#表示行结尾;
#,+#  表示从左侧#表示的行起始,加上右侧#表示的行数;
.   点号表示当前行
$  表示最后一行
.,$-1  表示当前行到倒数第2行
%  表示全文, 相当于1,$

/patern1/,/parten2/  表示从第一次被parten1模式匹配到的行开始,一直到第一次被parten2匹配到的行结束;
#,/parten/  表示从第#行到被parten模式匹配到的行
/parten/,$   表示从被parten匹配到的行开始到最后一行

地址定界之后,后面直接跟上编辑命令,比如
d  删除
y  复制
w /PATH/TO/SOMEWHERE  将范围内的行另存至指定文件中;
r  /PATH/FROM/SOMEFILE   在指定位置插入指定文件中的所有内容;

(2) 查找
/PATTERN  表示从当前光标所在处向文件尾部查找;
?PATTERN  表示从当前光标所在处向文件首部查找;
      n:与命令同方向;
      N:与命令反方向;

(3) 查找并替换
s  表示在末行模式下完成查找替换操作
s/要查找的内容/替换为的内容/修饰符
要查找的内容:可使用模式
替换为的内容:不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查找到的整个内容;
修饰符有2个,如下:
i  表示忽略大小写
g 表示全局替换;默认情况下,每一行只替换第一次出现;
查找替换中的分隔符/可使用其它任意字符,例如 s@@@或者s###
Note:这个查找并替换命令前面必须使用地址界定。

练习:
1、复制/etc/grub2.cfg至/tmp/目录,用查找替换命令删除/tmp/grub2.cfg文件中的行首的空白字符;
:%s/^[[:space:]]\+//g
2、复制/etc/rc.d/init.d/functions文件至/tmp目录,用查找替换命令为/tmp/functions的每行开头为空白字符的行的行首添加一个#号;
:%s/^[[:space:]]/#&/

VIM的多文件模式:
vim FILE1 FILE2 FILE3 ...
      :next 下一个
      :prev 前一个
      :first 第一个
      :last 最后一个
      :wall 保存所有
      :qall 退出所有

窗口分隔模式:
vim -o|-O FILE1 FILE2 ...
-o: 水平分割
-O: 垂直分割
在窗口间切换:按Ctrl+w之后松开,按方向键上,下,左,右选择

单文件窗口分割:
按Ctrl+w之后松开,按s键  表示split, 水平分割
按Ctrl+w之后松开,按v键  表示vertical, 垂直分割

定制vim的工作特性:
配置文件:永久有效
      全局:/etc/vimrc
      个人:~/.vimrc   如果不存在,自己创建即可
      末行:当前vim进程有效
(1) 行号
      显示:set number, 简写为set nu
      取消显示:set nonumber, 简写为set nonu
(2) 括号匹配
      匹配:set showmatch, 简写为set sm
      取消:set nosm
(3) 自动缩进
      启用:set ai
      禁用:set noai
(4) 高亮搜索
      启用:set hlsearch
      禁用:set nohlsearch
(5) 语法高亮
      启用:syntax on
      禁用:syntax off
(6) 忽略字符的大小写
      启用:set ic
      不忽略:set noic

获取帮助:
      :help
      :help subject

问题:如何设置tab缩进为4个字符?

练习:
1、复制/etc/rc.d/init.d/functions文件至/tmp目录;替换/tmp/functions文件中的/etc/sysconfig/init为/var/log;
:%s@/etc/sysconfig/init@/var/log@g

2、删除/tmp/functions文件中所有以#开头,且#后面至少有一个空白字符的行的行首的#号;
:%s@^#\([[:space:]]\+\)@\1@


评论

此博客中的热门博文

OAuth 2教程

网格策略

apt-get详细使用