Zhou Study hard, improve every day.

shell sed和awk学习

2020-04-27
   
本文 4739 字,阅读全文约需 14 分钟

sed的用法

sed(stream editor)是流编辑器,可对文本文件和标准输入进行编辑。 sed只是对缓冲区中原始文件的副本进行编辑,并不编辑原始的文件,如果需要保存改动内容,可以选择使用下面两种方法: 重定向 w编辑命令 -i 选项 sed基本格式

sed option 'script' file1 file2 ...
sed option -f scriptfile file1 file2 ...

选项含义:

--version            显示sed版本。
--help               显示帮助文档。
-n,--quiet,--silent  静默输出,默认情况下,sed程序在所有的脚本指令执行完毕后,将自动打印模式空间中的内容,这些选项可以屏蔽自动打印。
-e script            允许多个脚本指令被执行。
-f script-file, 
--file=script-file   从文件中读取脚本指令,对编写自动脚本程序来说很棒!
-i,--in-place        直接修改源文件,经过脚本指令处理后的内容将被输出至源文件(源文件被修改)慎用!
-l N, --line-length=N 该选项指定l指令可以输出的行长度,l指令用于输出非打印字符。
--posix             禁用GNU sed扩展功能。
-r, --regexp-extended  在脚本指令中使用扩展正则表达式
-s, --separate      默认情况下,sed将把命令行指定的多个文件名作为一个长的连续的输入流。而GNU sed则允许把他们当作单独的文件,这样如正则表达式则不进行跨文件匹配。
-u, --unbuffered    最低限度的缓存输入与输出。

以上仅是sed程序本身的选项功能说明,至于具体的脚本指令(即对文件内容做的操作)后面我们会详细描述.

  • sed的语法:sed ‘样式命令’文件 sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。(通过非交互式来修改文本中的内容)

意思是 如果文件中的某一行符合样式,就执行指定的sed命令 如删除(d)替换是(s) “样式”使用一对//含括,表示寻找的意思。也可以指定数据行的范围:如1,6 注意 sed不加”-i”的情况下是不修改文件内容的 只是读取文件的内容 »

p   打印匹配行
=   打印文件行号
a\  在定位行号之后追加文本信息
i\  在定位行号之前插入文本信息
d   删除定位行
c\  用新文本替换定位文本
s   使用替换模式替换相应模式
r   从另一个文件中读文本
w   将文本写入到一个文件
y   变换字符
q   第一个模式匹配完成后退出
l   显示与八进制ASCII代码等价的控制字符
{}  在定位行执行的命令组
n   读取下一个输入行用下一个命令处理新的行
h   将模式缓冲区文本拷贝到保持缓冲区
H   将模式缓冲区文本追加到保持缓冲区
x   互换模式缓冲区和保持缓冲区内容
g   将保持缓冲区内容拷贝到模式缓冲区
G   将保持缓冲区内容追加到模式缓冲区
g 与s使用表示全局匹配替换  
p 打印匹配行  
s 替换  
-n 取消默认输出  
-e 允许多项编辑  
-i 修改原文件  

sed基本用法

sed删除用法
sed ‘1,4d’dataf1 #把第一行到第四行删除,并且显示剩下的内容  
sed ‘/La/d’dataf2 #把含有La的行删除  
sed '/La/!d' dataf2  #把不含La的行删除,!是否定的意思  
sed ‘/[0-9]\{3\}/d’dataf3#把有”3位数”的行删除sed  
sed '/^$/d' dataf5  #删除空行  
sed 显示用法  
sed -n '/La/p' dataf2#显示含有La的行  
sed 替换用法(把-n 换成-i 就是直接替换原文件了)  
sed -n 's/La/Oo/p' dataf2 #把La替换为Oo-n是抑制sed显示其他行  
sed -n 's/La//p' dataf2 #把La替换为空  
sed -n 's/La/Oo/gp' dataf2  #加g是全局替换的意思  
sed -n 's/^...//p' dataf2  #把每行开头的3个字符替换为空  
sed -n 's/...$//p' dataf2 #把每行结尾的3个字符替换为空  
sed -n 's/La/10o/p' dataf2 #替换  
sed -n '/AAA/s/234/567/p' dataf6#找到含有AAA的行,然后把234替换成567  
sed -n '/AAA/,/DDD/s/B/567/p' dataf7#找到含有AAA到DDD的那几行,将B替换成567   
sed -n '/AAA/,/DDD/s/B/567/gp' dataf7   #全局
sed -n "/^[[:space:]]*Port/cPort 22" /etc/ssh/sshd_config  修改ssh连接端口

awk的用法

awk是一种编程语言,软件级别等同于bash,主要用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。 awk的工作方式是读取数据文件,将每行数据视为一条记录,每笔记录以字段分隔成若干个字段,然后输出各个字段的值 awk比sed强的地方在于不仅能以行为单位还能以列为单位处理文件。awk缺省的行分隔符是换行,缺省的列分隔符是连续的空格和Tab,但是行分隔符和列分隔符都可以自定义,比如/etc/passwd文件的每一行有若干个字段,字段之间以:分隔,就可以重新定义awk的列分隔符为:并以列为单位处理这个文件 awk的常用格式

awk "样式" 文件 : 把符合样式的数据行显示出来  
awk '{操作}' 文件: 对每一行都执行{}中的操作  
awk '样式{操作}' 文件: 对符合样式的数据行,执行{}中的操作  
1)命令模式
        awk [options] 'commands' file(s)
            command 部分:/范围说明/{awk命令语句1awk命令语句2}
                范围说明部分可以是BEGINEND、逻辑表达式或者为空
                awk命令语句间用分号间隔
                引用shell 变量需用双引号引起
            option 部分
                -F 定义字段分割符号
        
2)脚本模式
        awk [options] -f scriptfile file(s)
        特点:
            awk脚本是awk命令的清单
            命令需要用分号间隔
            #号开头的是注释行
            # /bin/awk -f 
变量名 属性
$0 当前记录
$1~$n 当前记录的第N个字段
FS 输入字段分隔符默认是空格
RS 输入记录分割符,默认为换行符
NF 当前记录中的字段个数,就是有多少列
NR 以及读出的记录数,就是行号,从1开始
OFS 输出字段分隔符 默认也是空格
ORS 输出的记录分隔符 默认为换行符

awk的示例

取倒数第一列和倒数第二列
$ head -1 passwd |awk -F':' '{print $NF,$(NF-1)}'
/bin/bash /root
换行符(默认处理一行后才换行)
$ head -1 passwd |awk -F':' '{print $NF RS $(NF-1)}'
/bin/bash
/root
$head -1 passwd | awk 'BEGIN {FS=":"} {print $NF RS $(NF-1)}' 

一次指定多个分隔符
$ awk -F':|/' '{print NF}' passwd 
$ awk -F'[:/]' '{print NF}' passwd 
$ ifconfig eth0|grep Bcast|awk -F':| +' '{print $4}'
$ifconfig eth0 |grep Bcast | awk -F" " '{print $2}'|awk -F":" '{print $2}'

打印标题和结尾信息
$ awk -F':'  'BEGIN {print "user\tpasswd\thome"RS"----------------------"} ; {print $1"\t"$2"\t"$(NF-1)} ; END {print "<-----------END---------->"}' passwd 
user    passwd  home
----------------------
root    x       /root
bin     x       /bin
daemon  x       /sbin
adm     x       /var/adm
lp      x       /var/spool/lpd
<-----------END---------->
正则表达式
awk '/La/' dataf3 #显示含有La的数据行    
awk '{print $1, $2}' dataf3 #显示dataf3每一行的第一个和第二个字段  
awk ‘/La/{print $1, $2}’ dataf3#将含有关键词La的数据行的第1和第2个字段显示  
awk -F: '/^ceshi/{print $3, $4}' /etc/passwd #用-F指定:为分隔符,账号ols3的第三段和第四段显示  
awk -F: 'BEGIN{OFS="+++"}/^mail/{print $1, $2, $3, $4, $5, $6, $7}' /etc/passwd
OFS的作用是存储输出字段的分隔符  
awk应用  
取网卡的IP地址  
ifconfig |sed -n '2p' |awk -F: '{print $2}' |awk '{print $1}'
取网络设备的名称:  
cat /proc/net/dev/sed -n '4p'|awk -F: '{print $1}'  
取系统内存大小  
cat /proc/meminfo |awk '/MemTotal/{print $1,$2}'
cat /proc/meminfo |sed -n '1p'
用netstat -ntl 截取所有开放的端口号
netstat -ntl |grep -v Active| grep -v Proto|awk '{print $4}'|awk -F: '{print $NF}'
netstat -ntlup |grep -Ev "Active|Proto" |awk '{print $4}' |awk -F: '{print $NF}'

awk流程控制
if
# awk -F: '{if($3>500) print $1,$3,"普通用户"}' /etc/passwd
# awk -F: '{if($3>500) print $1,$3,"普通用户";else print $1,$3,"不是普通用户"}' /etc/passwd
# awk -F: '{if($3==0) print $1,$3,"管理员";else if($3<500) print $1,$3,"系统用户";else print $1,$3,"普通用户"}' /etc/passwd
for 
# awk 'BEGIN {for(i=0; i<=10; i++) print i}'

while
# awk 'BEGIN {i=0;while(i<=5) {print i;i++}}'
# awk 'BEGIN {i=0;while(i<=5) {print"service",i,"start";i++}}'

#循环的控制:
break       --条件满足的时候中断循环
continue        --条件满足的时候跳过循环
# awk 'BEGIN {i=0;while(i<=5) {i++;if(i==3) continue; print i}}'
# awk 'BEGIN {i=0;while(i<=5) {i++;if(i==3) break; print i}}

下一篇 shell练习题

Comments

Content