内容简介:sed和awk的用例及pam安全措施-第十五周
总结sed和awk的详细用法;
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) 单地址
#:指定的行 $:文件的最后一行 /PATTERN/:被模式匹配到的每一行
(3) 地址范围
m,n:指定m行到n行 #,+n:指定#行到#+n行 /pat1/,/pat2/:匹配到的pat1到pat2之间的行 #,/pat/:第#行到匹配到pat
(4) 步进:~
1~2:所有奇数行,从一开始,步进2 2~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###
替换标记(flags):
#:替换行内匹配到的第#次的内容
g:行内全局替换
p:显示替换成功的行
w /PATH/TO/SOMEFILE:将替换后的结果保存至指定文件
replacement:
&:用pattern匹配到的内容进行替换
\n:在pattern中使用\(\)指定时,匹配第n个子串
【难点】高级编辑命令:
h:把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g:把保持空间中的内容覆盖至模式空间中;
G:把保持空间中的内容追加至模式空间中;
x:把模式空间中的内容与保持空间中的内容互换;
n:显示并清空模式空间,然后读取匹配到的行的下一行覆盖至模式空间;
N:追加读取匹配到的行的下一行至模式空间中;
d:删除模式空间中的行;
D:删除多行模式空间中的所有行;
示例:
sed -n 'n;p' FILE:显示偶数行;
sed '1!G;h;$!d' FILE:逆序显示文件的内容;
sed ’$!d' FILE:取出最后一行;
sed '$!N;$!D' FILE:取出文件后两行;
sed '/^$/d;G' FILE:删除原有的所有空白行,而后为所有的非空白行后添加一个空白行;
sed 'n;d' FILE:显示奇数行;
sed 'G' FILE:在原有的每行后方添加一个空白行;
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, …
格式符:
%c: 显示字符的ASCII码;
%d, %i: 显示十进制整数;
%e, %E: 科学计数法数值显示;
%f:显示为浮点数;
%g, %G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%: 显示%自身;
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
%3.1f
-: 左对齐
+:显示数值的符号
记住哦,格式符和修饰符可以灵活组合使用
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
语法:if(condition) statement [else statement]
~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
~]# awk '{if(NF>5) print $0}' /etc/fstab
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
使用场景:对awk取得的整行或某个字段做条件判断;
while循环
语法:while(condition) statement
条件“真”,进入循环;条件“假”,退出循环;
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;
do-while循环
语法:do statement while(condition) 意义:至少执行一次循环体
for循环
语法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
特殊用法:
能够遍历数组中的元素;
语法:for(var in array) {for-body}
switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}
next
提前结束对本行的处理而直接进入下一行;
~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
数组array
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
weekdays[mon]="Monday"
若要遍历数组中的每个元素,要使用for循环;
for(var in array) {for-body}
函数
内置函数
数值处理:
rand():返回0和1之间一个随机数;
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
好,上边ACTION啰嗦完了,哈哈哈哈哈,下面就要高潮咧O(∩_∩)O哈哈~
PATTERN
PATTERN有什么,有很多,超乎你的想象,它支持
(1) empty:空模式,匹配每一行;
(2) /regular expression/:仅处理能够被此处的模式匹配到的行;
(3) relational expression: 关系表达式;【结果有“真”有“假”;结果为“真”才会被处理】;
【真:结果为非0值,非空字符串】这个跟bash的命令返回值不一样;
(4) line ranges:行范围,
startline,endline:/pat1/,/pat2/
例子:[root@CentOS7 ~]# awk -F: '/^h/,/^u/{print $1}' /etc/passwd
注意: 不支持直接给出数字的格式
可以使用如下方式:
~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
(5) BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
END{}:仅在文本处理完成之后执行一次 ;
选项[options]
-F:指明输入时用到的字段分隔符;
-v var=value: 自定义变量;
awk的options主要用来定义各种变量和使用各种內建变量。
内建变量
FS:input field seperator,默认为空白字符;
OFS:output field seperator,默认为空白字符;
RS:input record seperator,输入时的换行符;
ORS:output record seperator,输出时的换行符;
NF:number of field,字段数量
{print NF}, {print $NF} 它们之间是有区别的,NF是有多少个字段数量,而$NF表示最后一个字段的内容
NR:number of record, 行数;
FNR:各文件分别计数;行数;
$0:代表一行,读一行进行切片
FILENAME:当前文件名;
ARGC:命令行参数的个数;
ARGV:数组,保存的是命令行所给定的各参数;
PS:在awk中要做变量替换,是不能用引号引起来的
自定义变量
(1) -v var=value #变量名区分字符大小写哦;
(2) 在program中直接定义
好了,awk就介绍到这里,下面来写例子
例子1:显示/etc/passwd的账户
#cat /etc/passwd |awk -F ':' '{print $1}'
root
daemon
bin
sys
上边这种是awk+action的示例,每行都会执行action{print $1}。
-F指定域分隔符为’:’。
例子2:搜索/etc/passwd有root关键字的所有行
#awk -F: '/root/' /etc/passwd root:x:0:0:root:/root:/bin/bash
上边这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。
搜索支持正则,例如找root开头的: awk -F: ‘/^root/’ /etc/passwd
例子3:搜索/etc/passwd有root关键字的所有行,并显示对应的shell
# awk -F: '/root/{print $7}' /etc/passwd
/bin/bash
上边这里指定了匹配了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#(\/.*\/)##’
上边的sed分隔符为#,用到了sed的查找替换、正则表达式及其分组,形式为\(正则表达式\) 正则为\/.*\/,其中\为转移符,正则抽取出来就是/.*/ 意思就是匹配到/开头的以/结尾期间的任意单个字符任意次。 各位应该明白了吧。
例子8:统计指定文件中所有行中每个单词出现的次数
awk ‘{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}’ /etc/fstab
[root@CentOS7 ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
swap 2
fstab(5), 1
filesystems, 1
on 1
/etc/fstab 1
/boot 1
more 1
mount(8) 1
pages 1
'/dev/disk' 1
/dev/mapper/cl_centos7-swap 1
blkid(8) 1
See 1
/dev/mapper/cl_centos7-root 1
for 1
and/or 1
anaconda 1
/ 1
findfs(8), 1
under 1
17:33:09 1
Created 1
UUID=fe2021fb-ac21-474d-8256-f72b87fc915a 1
0 6
info 1
Accessible 1
22 1
# 7
defaults 3
xfs 2
man 1
are 1
reference, 1
Mar 1
by 2
maintained 1
2017 1
Wed 1
[root@CentOS7 ~]#
7、统计当前系统上所有tcp连接的各种状态的个数;
netstat -n | awk ‘/^tcp/ {++state[$NF]} END {for(key in state) print key,”t”,state[key]}’
例子
root@xxx:~# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"t",state[key]}'
FIN_WAIT2 t 71
CLOSE_WAIT t 1
TIME_WAIT t 2049
ESTABLISHED t 1392
LAST_ACK t 3
FIN_WAIT1 t 4
8、统计指定的web访问日志中各ip的资源访问次数:
awk ‘{ip[$1]++}END{for(i in ip) print i,ip[i]}’ /opt/nginx/logs/access.log
9、写一个脚本:定义一个数组,数组元素为/var/log目录下所有以.log结尾的文件的名字;显示每个文件的行数;
[root@CentOS7 ~]# cat week15_title9.sh
#!/bin/bash
files=/var/log/*.log
for i in $files
do
wc -l $i
done
输出如下:
[root@CentOS7 ~]# ./week15_title9.sh 248 /var/log/boot.log 9 /var/log/openlmi-install.log 177 /var/log/vmware-install.log 326 /var/log/vmware-vmsvc.log 85 /var/log/vmware-vmusr.log 10 /var/log/wpa_supplicant.log 436 /var/log/Xorg.0.log 320 /var/log/Xorg.9.log 328 /var/log/yum.log [root@CentOS7 ~]#
10、写一个脚本,能从所有同学中随机挑选一个同学回答问题;进一步地:可接受一个参数,做为要挑选的同学的个数;
[root@CentOS7 ~]# cat week15_title10.sh
#!/bin/bash
if [ $1 ];then #判断有无脚本参数传入,如有则执行,没有就执行else的语句
for((i=1;i<=$1;i++));do
a=$[$RANDOM%11] #定义一个0~10的随机数
echo $a
done
else
a=$[$RANDOM%11]
echo $a
fi
11、授权centos用户可以运行fdisk命令完成磁盘管理,以及使用mkfs或mke2fs实现文件系统管理;
visudo centos ALL=(root) NOPASSWD:/sbin/fdisk,/sbin/mke2fs,/sbin/mkfs
12、授权gentoo用户可以运行逻辑卷管理的相关命令;
visudo gentoo ALL=(root) lvm
13、基于pam_time.so模块,限制用户通过sshd服务远程登录只能在工作时间进行;
vim /etc/ssh/sshd_config UsePAM yes #开启Pam模块认证 /lib64/security/pam_time.so #确保pam_time.so存在 vim /etc/pam.d/sshd 增加 account required pam_time.so vim /etc/security/time.conf 添加 *;*;*;MoTuWeThFr0900-1800
14、基于pam_listfile.so模块,定义仅某些用户,或某些组内的用户可登录系统;
[root@localhost ~]# vim /etc/sshd_userlist root centos gentoo chmod 600 /etc/sshd_userlist chown root /etc/sshd_userlist vim /etc/pam.d/sshd #auth required pam_listfile.so item=user sense=allow file=/etc/sshd_userlist onerr=succeed
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Domain-Driven Design
Eric Evans / Addison-Wesley Professional / 2003-8-30 / USD 74.99
"Eric Evans has written a fantastic book on how you can make the design of your software match your mental model of the problem domain you are addressing. "His book is very compatible with XP. It is n......一起来看看 《Domain-Driven Design》 这本书的介绍吧!