sed和awk的用例及pam安全措施-第十五周

总结sed和awk的详细用法;

sed用法

sed(Stream EDitor)是一款流编辑器,用来对文本进行过滤与替换操作。其原理是:通过文件或管道读取文件内容,但是sed默认并不直接修改源文件,而是一次仅读取文件的一行至模式空间(pattern space)根据sed指令进行编辑并输出结果后清除模式空间,即所有的操作都是在模式空间中进行的。

sed和awk的用例及pam安全措施-第十五周

语法格式

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

语法:

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

原创文章,作者:N24_Jerry,如若转载,请注明出处:http://www.178linux.com/77539

(0)
N24_JerryN24_Jerry
上一篇 2017-06-05
下一篇 2017-06-05

相关推荐

  • python面向对象第二周魔术方法详解

    魔法方法及其使用__开头和结束的方法,定义外部没有办法直接调用,但会有影响使用运算符号的魔法方法, + ,-,*,/,%,//,**, __add__,__sub__,__mul__,__truediv__,__mod__,__floordiv__,__pow__,__divmod__(?),系统内部对于数值型,字符串型,容器内型都定义了其中部分或者全部的运…

    Linux干货 2017-11-22
  • 文件查找命令find

      在文件系统上常常需要根据文件的各种属性去查找符合条件的文件。在Linux下也有相当优异的查找命令。今天只要将find和locate。find通常不常用,因为速度慢!通常我们先使用locate来进行模糊查找,如果真找不到了,才以find来查找。为什么呢?因为locate是利用数据库来查找数据,所以速度非常快,而且并没有实际查询硬盘比较省时间。 l…

    Linux干货 2016-08-22
  • DNS配置

     DNS配置 基本的配置准备 1.安装bind 2.开启named服务 一、正向解析库 1、修改/etc/named.conf配置文件 vim /etc/named.conf 修改如下行 listen-on port 53 { 10.1.44.2; } allow-query     { any; } recursion no;…

    Linux干货 2016-10-09
  • 20160810作业

    1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小。           2、编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到/root…

    Linux干货 2016-08-12
  • 在马哥学习linux第一天的感受

         来马哥教育好几天了,昨天算是正式开始,在昨天早上,举行了开班典礼,各位老师助教为我们介绍了在马哥教育进行培训的相关注意事项,下午进行了两场测试,首先有一个摸底测试,不得不说我真的是太菜了,除了一些比较简单的题目我还有些把握,相当一部分我都是似曾相识,但是也不是很确定,还有很大一部分我根本听都没听说过,看到别人都写的满满…

    Linux干货 2017-07-11
  • 第四周博客分享

                    时间匆匆,转眼来马哥已经快一个月了,这一个月对我来说是收获满满,每天都在学到新的东西。       &nbs…

    2017-08-06