sed用法
sed(Stream EDitor)是一款流编辑器,用来对文本进行过滤与替换操作。其原理是:通过文件或管道读取文件内容,但是sed默认并不直接修改源文件,而是一次仅读取文件的一行至模式空间(pattern space)根据sed指令进行编辑并输出结果后清除模式空间,即所有的操作都是在模式空间中进行的。
语法格式
sed [option]… ‘script’ inputfile…
OPTIONS选项
-n,–quite,–silent:静默输出,即不输出模式中的内容至输出
-e script:使用多个脚本指令执行编辑
-f /PATH/TO/SCRIPT_FILE:从指定的文件中读取编辑脚本
-r:支持在脚本中使用正则表达式
-i,–in-place:直接在文件原处执行编辑,即修改源文件
SCRIPT,地址定界+编辑指令
地址定界
(1) 不给地址:对全文进行处理;
(2) 单地址
1 | #:指定的行 |
(3) 地址范围
1 | m,n:指定m行到n行 |
(4) 步进:~
1 | 1~2:所有奇数行,从一开始,步进2 |
注意:如果//中正则表达式为空,则匹配最近一次正则表达式的匹配地址!
编辑命令
d:删除
p:显示模式空间的内容
a \text:在行后面追加内容,支持使用\n(换行符)实现多行追加
i \text:在行前面插入内容,支持使用\n(换行符)实现多行追加
c \text:替换行为单行或多行文本,支持使用\n(换行符)
w /PATH/TO/SOMEFILE:保存模式空间匹配到的行至指定文件中
r /PATH/FROM/SOMEFILE:读取指定文件的文本流至模式空间中匹配到的行的行后
=:为模式空间中的行打印行号
!:取反条件
s/pattern/replacement/flags:替换,支持使用其他分隔符,如:s@@@, s###
1 | 替换标记(flags): |
【难点】高级编辑命令:
1 | h:把模式空间中的内容覆盖至保持空间中; |
awk用法
其用法博大精深,且听我细细道来
首先,grep,sed,awk三者区别,回顾一下:
grep, egrep, fgrep
文本过滤工具,只读不写,加上各种正则及关键字,那叫一个爽快。
sed
行编辑器,有模式空间及保持空间,实现文本行的编辑及输出。
awk
报告生成器,格式化文本输出;功能及其强大,不光可用正则,还可以使用条件判断语句,函数、数组,不愧为上古神器。
有一点很重要,也很激励人心,就是“结合awk与其他工具诸如grep和sed,将会使shell编程更加容易,也更有逼格。”
awk命令的使用格式:
awk [options] ‘program’ file1,file2,…
awk [options] ‘PATTERN { action }’ file1,file2,…
program与PATTERN { action }的关系
很多同学在刚开始学习awk的时候,这里常常犯迷糊,me too!所以我觉得这个关系先理清楚,对awk往后的学习是有帮助的。
program包括PATTERN和ACTION,PATTERN和ACTION最少得有一个,语句之间用分号分隔
【理解关键点】模式( pattern ) 用于匹配输入中的每行文本。对于匹配上的每行文本,awk 都执行对应的 动作( action )。模式和动作之间使用花括号隔开。awk 顺序扫描每一行文本,并使用 记录分隔符(一般是换行符)将读到的每一行作为 记录,使用 域分隔符( 一般是空格符或制表符 ) 将一行文本分割为多个 域, 每个域分别可以使用 $1, $2, … $n 表示。$1 表示第一个域,$2 表示第二个域,$n 表示第 n 个域。 $0 表示整个记录。模式或动作都可以不指定,缺省模式的情况下,将匹配所有行。缺省动作的情况下,将执行动作 {print},即打印整个记录。
先来说说ACTION
其中最常用的ACTION参数之一就是print和printf了,前者实现打印输出,后者实现格式化输出
语法:
print item1, item2, …
要点
(1) 逗号分隔符;
(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式;
(3) 如省略item,相当于print $0,打印整行字符
printf命令,这个就很有内涵了
要点:
(1) FORMAT必须给出;
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面的每个item指定一个格式化符号;
语法:
printf 格式符/修饰符, item1, item2, …
1 | 格式符: |
记住哦,格式符和修饰符可以灵活组合使用
ACTION还支持以下干货
(1) Expressions表达式
(2) Control statements:if, while等;
(3) Compound statements:组合语句;
(4) input statements
(5) output statements(print printf)
我们来看看控制语句:
(1)if(condition) {statments} :单分支if语句
(2)if(condition) {statments} else {statements} :双分支if语句
(3)while(conditon) {statments}
(4)do {statements} while(condition) :循环体
(5)for(expr1;expr2;expr3) {statements}
(6)break
(7)continue
(8)delete array[index]
(9)delete array
(10)exit
支持这么多,已经看傻,下面一个个来看看:
if-else
1 | 语法:if(condition) statement [else statement] |
while循环
1 | 语法:while(condition) statement |
do-while循环
1 | 语法:do statement while(condition) |
for循环
1 | 语法:for(expr1;expr2;expr3) statement |
switch语句
1 | 语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement} |
next
1 | 提前结束对本行的处理而直接进入下一行; |
数组array
1 | 关联数组:array[index-expression] |
函数
1 | 内置函数 |
好,上边ACTION啰嗦完了,哈哈哈哈哈,下面就要高潮咧O(∩_∩)O哈哈~
PATTERN
PATTERN有什么,有很多,超乎你的想象,它支持
1 | (1) empty:空模式,匹配每一行; |
选项[options]
-F:指明输入时用到的字段分隔符;
-v var=value: 自定义变量;
awk的options主要用来定义各种变量和使用各种內建变量。
内建变量
1 | FS:input field seperator,默认为空白字符; |
自定义变量
1 | (1) -v var=value #变量名区分字符大小写哦; |
好了,awk就介绍到这里,下面来写例子
例子1:显示/etc/passwd的账户
1 | #cat /etc/passwd |awk -F ':' '{print $1}' |
上边这种是awk+action的示例,每行都会执行action{print $1}。
-F指定域分隔符为’:’。
例子2:搜索/etc/passwd有root关键字的所有行
1 | awk -F: '/root/' /etc/passwd |
上边这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。
搜索支持正则,例如找root开头的: awk -F: ‘/^root/‘ /etc/passwd
例子3:搜索/etc/passwd有root关键字的所有行,并显示对应的shell
1 | awk -F: '/root/{print $7}' /etc/passwd |
上边这里指定了匹配了pattern(这里是root)的行才会执行action{print $7}
例子4:删除/boot/grub/grub.conf文件中所有行的行首的空白字符
sed ‘s/^[[:space:]]+//‘ /boot/grub/grub.conf
这里的sed使用了查找替换,思路就是先查找文件中所有行的行首的空白字符,用正则的行首锚定空字符,之后查找替换为空,即删除。
例子5:删除/etc/fstab文件中所有以#开头,后跟至少一个空白字符的行的行首的#和空白字符
sed ‘s/^#[[:space:]]*//‘ /etc/fstab
同样是查找替换的套路,参照例子4
例子6:把/etc/fstab文件的奇数行另存为/tmp/fstab.3
sed ‘1~2!d’ /etc/fstab > /tmp/fstab.3
sed ‘1~2w /tmp/fstab.3’ /etc/fstab
这里用到了sed地址定界中的步进+编辑命令,两种不同的编辑命令实现,真是飞刀又见飞刀,套路又见套路,套路就是熟悉其语法,命令,灵活组合使用。
例子7:echo一个文件路径给sed命令,取出其基名;进一步地,取出其路径名
路径名
echo “/tmp/test/fstab” | sed ‘s#[^/]+\?$##’
上边sed的#为分隔符,[^/]指匹配指定范围外的任意单个字符,
+:匹配其前面的字符1次或多次:即其前面的字符要出现至少1次;
\?:匹配其前面的字符0次或1次;即其前面的字符是可有可无的;
$:行尾锚定;用于模式的最右侧
基名
echo “/tmp/test/fstab” | sed ‘s#(\/.*\/)##’
1 | 上边的sed分隔符为#,用到了sed的查找替换、正则表达式及其分组,形式为\(正则表达式\) |
例子8:统计指定文件中所有行中每个单词出现的次数
awk ‘{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}’ /etc/fstab
1 | [root@CentOS7 ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab |
7、统计当前系统上所有tcp连接的各种状态的个数;
netstat -n | awk ‘/^tcp/ {++state[$NF]} END {for(key in state) print key,”t”,state[key]}’
例子
1 | root@xxx:~# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}' |
8、统计指定的web访问日志中各ip的资源访问次数:
awk ‘{ip[$1]++}END{for(i in ip) print i,ip[i]}’ /opt/nginx/logs/access.log
9、写一个脚本:定义一个数组,数组元素为/var/log目录下所有以.log结尾的文件的名字;显示每个文件的行数;
1 | [root@CentOS7 ~]# cat week15_title9.sh |
输出如下:
1 | [root@CentOS7 ~]# ./week15_title9.sh |
10、写一个脚本,能从所有同学中随机挑选一个同学回答问题;进一步地:可接受一个参数,做为要挑选的同学的个数;
1 | [root@CentOS7 ~]# cat week15_title10.sh |
11、授权centos用户可以运行fdisk命令完成磁盘管理,以及使用mkfs或mke2fs实现文件系统管理;
1 | visudo |
12、授权gentoo用户可以运行逻辑卷管理的相关命令;
1 | visudo |
13、基于pam_time.so模块,限制用户通过sshd服务远程登录只能在工作时间进行;
1 | vim /etc/ssh/sshd_config |
1 | /lib64/security/pam_time.so #确保pam_time.so存在 |
14、基于pam_listfile.so模块,定义仅某些用户,或某些组内的用户可登录系统;
1 | [root@localhost ~]# vim /etc/sshd_userlist |