linux的awk和sed等命令比较

对于文本的操作分为两种操作,一种是按行操作,一种是按列操作。
简单的命令有grep(行操作)和cut(列操作)。
复杂点的有sed(行操作)和awk(列操作)。
样例文本

hello tom
hi marry
how are you

什么是行操作:简单的例子就是,获取上面文本中带有hello的行就是行操作。
什么是列操作:简单的例子就是获取上面文本中的第一列操作。

grep

package com.zzrenfeng.linux;
/**
 * grep命令
 * 
 * @author hanlipeng
 *
 */
public class Grep {


/**
 * [options]主要參数:
 * -c:仅仅输出匹配行的计数。
 * -I:不区分大 小写(仅仅适用于单字符)。
 * -h:查询多文件时不显示文件名称。
 * -l:查询多文件时仅仅输出包括匹配字符的文件名称。
 * -n:显示匹配行及 行号。
 * -s:不显示不存在或无匹配文本的错误信息。
 * -v:显示不包括匹配文本的全部行。
 * 
 * 命令正則表達式:

 * . 匹配单个字符 如..X  yiX能查出来
 * ^ 匹配行首 ^d 每行第一个字符为d
 * $ 匹配行尾 T$ 每行最后一个字符为T
 * 匹配随意字符串
 * \ 屏蔽特殊字符的含义
 * A\{2\}B 字母A出现两次
 * A\{2,\}B 至少出现两次
 * A\{2,4\}B 出现2到4次
 * [0-9]\{4\}xx[0-9]\{4\} 前四个是数字,中间是xx,后四个是数字
 * 
 * 简单实用
 * 过滤出行里面有hello的行
 * grep 'hello' filename.txt
 * 
 * 过滤出所有行里面不含hello的行 
 * grep -v 'hello' filename.txt
 * 
 */

}

cut(里面附带了sort,wc,uniq操作)

package com.zzrenfeng.linux;
/**
 * cut用法
 * 命令可以从一个文本文件或者文本流中提取文本列。
 * 
 * sort wc uniq
 * @author rf
 *
 */
public class Cut {
/**
 * cut的用法:cut是对列进行截取的 相当于awk的用法
 * 
 * 将 PATH 变量取出,我要找出第五个路径。
 * echo $PATH | cut -d ':' -f 5
 * 
 * 将 PATH 变量取出,我要找出第三和第五个路径。
 * echo $PATH | cut -d ':' -f 3,5
 * 
 * 将 PATH 变量取出,我要找出第三到最后一个路径。
 * echo $PATH | cut -d ':' -f 3-
 * 
 * 将 PATH 变量取出,我要找出第一到第三个路径。
 * echo $PATH | cut -d ':' -f 1-3
 */

/**
 * wc的命令
 * 
 * wc主要是进行统计的
 * wc -l /etc/passwd   #统计行数,在对记录数时,很常用
 * wc -w /etc/passwd  #统计单词出现次
 * wc -m /etc/passwd  #统计文件的字符数
 */

/**
 * sort [-fbMnrtuk] [file or stdin]
 * 
 * 选项与参数:
 * -f  :忽略大小写的差异,例如 A 与 a 视为编码相同;
 * -b  :忽略最前面的空格符部分;
 * -M  :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
 * -n  :使用『纯数字』进行排序(默认是以文字型态来排序的);
 * -r  :反向排序;
 * -u  :就是 uniq ,相同的数据中,仅出现一行代表;
 * -t  :分隔符,默认是用 [tab] 键来分隔;
 * -k  :以那个区间 (field) 来进行排序的意思
 * 
 * sort 是默认以第一个数据来排序,而且默认是以字符串形式来排序,所以由字母 a 开始升序排序。
 * 
 * 内容是以 : 来分隔的,我想以第三栏来排序,该如何
 * cat /etc/passwd | sort -t ':' -k 3
 * 
 * 默认是以字符串来排序的,如果想要使用数字排序:
 * cat /etc/passwd | sort -t ':' -k 3n
 * 
 * 默认是升序排序,如果要倒序排序,如下
 * cat /etc/passwd | sort -t ':' -k 3nr
 * 
 * 如果要对/etc/passwd,先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序。
 * cat /etc/passwd |  sort -t':' -k 6.2,6.4 -k 1r 
 * 
 * 查看/etc/passwd有多少个shell:对/etc/passwd的第七个域进行排序,然后去重:
 * cat /etc/passwd |  sort -t':' -k 7 -u
 */

/**
 * uniq [-icu]
 * 
 * 选项与参数:
 * -i   :忽略大小写字符的不同;
 * -c  :进行计数
 * -u  :只显示唯一的行
 * 
 * 注意:去重需要先排序,也就是只有两行是一块的才能去重
 */
}

sed

package com.zzrenfeng.linux;
/**
 * sed 是一种在线编辑器,它一次处理一行内容
 * 
 * @author hanlipeng
 *
 */
public class Sed {


/**
 * sed用法
 * 
 * 删除:d命令
 * sed '2d' example-----删除example文件的第二行。
 * sed '2,$d' example-----删除example文件的第二行到末尾所有行。
 * sed '$d' example-----删除example文件的最后一行。
 * sed '/test/'d example-----删除example文件所有包含test的行。
 * sed -i '2d' example-----删除会被回写到文件,不加-i不会改变源文件
 * 
 * 替换:s命令
 * sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。
 * sed -n 's/^test/mytest/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。
 * sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。
 * sed -n 's/\(love\)able/\1rs/p' example-----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。
 * sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。
 * 选定行的范围:逗号
 * 
 * 
 * 多点编辑:e命令
 * sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。
 * 
 * 从文件读入:r命令
 * sed '/test/r file' example-----file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。
 * 
 * 写入文件:w命令
 * sed -n '/test/w file' example-----在example中所有包含test的行都被写入file里。
 * 
 * 追加命令:a命令
 * sed '/^test/a\\--->this is a example' example    '----->this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。
 * 
 * 插入:i命令
 * sed '/test/i\\
 * 
 * 
 * 后面的命令看help吧
 */

}

awk

package com.zzrenfeng.linux;
/**
 * awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
 * 
 * @author hanlipeng
 *
 */
public class Awk {

/**
 * awk
 * 
 * 如果只是显示最近登录的5个帐号
 * last -n 5 | awk  '{print $1}'
 * 
 * 如果只是显示/etc/passwd的账户
 * cat /etc/passwd |awk  -F ':'  '{print $1}'
 * 
 * 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割
 * cat /etc/passwd |awk  -F ':'  '{print $1"\t"$7}'
 * 
 * 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。
 * cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
 * 
 * 搜索/etc/passwd有root关键字的所有行
 * awk -F: '/root/' /etc/passwd
 * 
 * 搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd
 * 
 * 搜索/etc/passwd有root关键字的所有行,并显示对应的shell
 * awk -F: '/root/{print $7}' /etc/passwd
 * 
 * awk内置变量
 * awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。
 * 
 *  
 * ARGC               命令行参数个数
 * ARGV               命令行参数排列
 * ENVIRON            支持队列中系统环境变量的使用
 * FILENAME           awk浏览的文件名
 * FNR                浏览文件的记录数
 * FS                 设置输入域分隔符,等价于命令行 -F选项
 * NF                 浏览记录的域的个数
 * NR                 已读的记录数
 * OFS                输出域分隔符
 * ORS                输出记录分隔符
 * RS                 控制记录分隔符
 * 
 * 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:
 * 
 * #awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
 * filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
 * filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh
 * filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
 * filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
 * 
 * 
 * 使用printf替代print,可以让代码更加简洁,易读
 * awk  -F ':'  '{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
 * 
 * 
 * 
 * 高级awk编程
 * 除了awk的内置变量,awk还可以自定义变量
 * 
 * 下面统计/etc/passwd的账户人数
 * awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
 * root:x:0:0:root:/root:/bin/bash
 * ......
 * user count is  40
 * 
 * 这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
 * awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
 * [start]user count is  0
 * root:x:0:0:root:/root:/bin/bash
 * ...
 * [end]user count is  40
 * 
 * 
 * 统计某个文件夹下的文件占用的字节数
 * ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
 * [end]size is  8657198
 *  
 * 
 * 如果以M为单位显示:
 * ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}' 
 * [end]size is  8.25889 M
 * 注意,统计不包括文件夹的子目录。
 * 
 * 
 */

/**
 * 条件语句以后需要了再进行学习

 awk中的条件语句是从C语言中借鉴来的,见如下声明方式:


if (expression) {
    statement;
    statement;
    ... ...
}

if (expression) {
    statement;
} else {
    statement2;
}

if (expression) {
    statement1;
} else if (expression1) {
    statement2;
} else {
    statement3;
}



统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):

ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}' 
[end]size is  8.22339 M


循环语句

awk中的循环语句同样借鉴于C语言,支持while、do/whileforbreak、continue,这些关键字的语义和C语言中的语义完全相同。



数组

  因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。



显示/etc/passwd的账户


awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......

这里使用for循环遍历数组
 */

}

你可能感兴趣的:(linux)