实际开发中,gerp 查找, sed 编辑, awk 根据内容分析.
sed ( 处理以行为单位 )sed 本身也是一个管线命令, 可以分析 standard input, 而且 sed 开可以将数据进行取代, 删除, 新增, 截取特定行 等等功能,
sed [-nefr][动作]
选项与参数:
-n : 使用安静模式, 一般sed用法中, 所有来自 stdin 的数据一般都会被列出到屏幕上, 但是如果加上 –n 参数后, 则之后经过 sed 特殊处理的那一行(或者动作) 才会被列出来.
-e : 直接在指令列模式上进行 sed 的动作编辑
-f :直接将sed 的动作卸载一个档案内, –f filename 则可以执行 filename 内的 sed 动作;
-r : sed 的动作支持的是延伸型的正则表达式语法, (默认的是基础正则表达式语法)
-i : 直接修改读取档案的内容, 而不是由屏幕输出.
动作说明: [n1,[n2]] function
n1, n2 不见得会存在, 一般代表[选择进行动作的行数], 例如, 需要再10-20行之间进行的, 则 10,20 动作行为.
function : 动作如下
a : 新增, a 后面可以接字符串, 而这些字符串会在新一行会粗线(目前的下一行)
c : 取代, c 后面可以接字符串, 这些字符串可以取代 n1, n2 之间的行
d : 删除, 因为是删除, 所以 d 后面通常不接任何东西
i :插入, i 后面可以接字符串, 而这些字符串会在新的一行出现(目前的上一个行)
p : 打印, 即将某个选择的数据打印, 通常 p 会与参数 sed –n 一起运作
s : 取代, 可以直接进行取代的工作, 通常这个 s 的动作可以搭配正则表达式, 例如: 1,20s/old/new/g
例如 :
1. 将 /etc/passwd 内容打印出来, 并显示行号, 并删除第2-5行
nl /etc/passwd | sed ‘2,5d’ // 注意, sed 后一定要接两个单引号括起来
nl /etc/passwd | sed –n ‘2,5d’ // 注意, 这时什么也打印不出来, 因为 –n 的意思是只是将特殊处理行打印出来, 但是我们的特殊处理是删除, 所以就没有任何显示.
nl /etc/passwd | sed '2,$d’ // 从第二行删除到最后一行
2. 插入一行数据 , 插入2行数据
nl /etc/passwd | sed ‘2i hello’ // 在第2行前插入 hello
nl /etc/passwd | sed ‘2a hello’ // 在第2行后插入 hello
nl /etc/passwd | sed ‘2a hello\ 然后再下一行输入 world!’ // 这样就插入2行, 前面1行为 hello, 后面一行为 world!', 这样就可以增加好几行, 不过每行结尾到要有 \
3. 以行为单位取代或显示
nl /etc/passwd | sed ‘2,3c hello,world’ // 这样就将2-3行取代为 hello, world
nl /etc/passwd | sed -n‘2,3p’ // 这样就只打印, 2-3行, 也可以使用 head –n 3 | tail –n 1 (但是这个没有 sed 用起来好 )
4. 部分数据的搜索与替代功能
nl /etc/passwd | sed ‘2,3s/aaa/xxx/g’ // 其中 2,3 为行数, 可以省略, 如果省略则是替换全文, s 表示替换 aaa 表示旧值, xxx表示新值, g 是一个格式
另外注意, 因为 sed 处理是以行为单位, 所以以上的替换 会替换行内所有的 aaa, 比如 一行内有 3个 aaa, 那么这3个aaa都会被替换.
5. 直接修改档案内容 ( 危险 )
例如 sed –i ‘s/\.$/\!/g’ regular_express.txt
sed –i ‘s/aaa/xxx/g’ regular_express.txt // 直接修改档案文件, 替换的办法跟前面一样, 所不同的是, 这样就直接修改了档案文件.
awk (数据处理工具, 可以将行按照指定分隔符分成很多个区域 )
相对于 sed 常常用于一整行的处理, awk 则比较倾向于一行当中分成数个”字段”(即区域)来处理, awk 通常运作模式为:
awk ‘条件类型1{动作1}条件类型2{动作2}…’ filename
awk 后面接两个单引号并加上大括号{}来设定想要对数据进行处理的动作. awk 可以处理后续接的档案即 filename, 也可以读取来自前一个指令的 standard output, 例如香港系统中的命令, 但如前面说, awk主要是处理每一行字段内的数据, 而默认的字段分隔符为”空格键”或tab键.
例如:
last –n 5 | awk ‘{print $1 “\t” $3}’ // 打印 第 1 个和 第3个区域, 用 “\t” 即 tab 来分隔显示
$0 代表整行, $1 代表第1个区域, $2 代表第2个区域, 依此类推
awk 的处理流程是:
1. 读入第一行, 并将第一行的资料填入 $0, $1, $2, … 等变量当中;
2. 依据”条件类型”的限制, 判断是否需要进行后面的”动作”;
3. 作完所有动作和条件类型;
4. 若还有后续的行的数据, 则重复上面的 1-3步骤, 直至所有的数据都读完为止.
所以, awk 是以行为 一次 处理单位, 而已区域为最小处理单位
另外, 还有3个变量, 分别是:
NF : 每一行($0) 拥有的字段数
NR : 目前 awk 所处理的是 第几行
FS : 目前的分隔符, 默认是空格键
注意: 因为 awk 后面必须接单引号, 所以在两个单引号之内, 例如需要使用 “\t” 时, 必须使用双引号, 因为引号要成对出现
last –n 5 | awk ‘{print $1 “\t” $2 “\t” NF “\t” NR “\t” FS}’
awk 的逻辑运算字符
> < >= <= == !==
cat /etc/passwd | awk ‘{FS=”:”} $3 < 10 {print $1 “\t” “$3”}’ // 这里的条件判断后边接{}, 这个大括号表示动作, 注意这里不是 if, else, 而是类似只有if, 就是说有一个条件, 后面跟一个动作, 这样
注意, 这里第一行显示有问题, 这是因为, 读取第1行是, FS = “:” 这条命令没有生效, 而默认的分隔符是空格, 所以这个文件的第一行就全部作为了第一个字段, 所以第1行就都显示出来了, 但是读取第2行时, 由于分隔符已经变成了 :所以, 第2 行以后就能正确显示, 那么怎么解决呢 ? 我们可以预先设定 awk 的变量, 利用 BEGIN 关键词:
cat /etc/passwd | awk ‘BEGIN {FS = “:”} $3 < 10 {print $1 “\t” $3}’
例如, 输出一个计算工资总和的例子: 数据的格式是这样的 :
Name Jan Feb Mar
张三 1000 1000 1000
李四 2000 2000 2000
王五 3000 3000 3000
因为我们要计算工资总和, 所以我们就要计算, 但是我们并不想计算第一行, 所以命令为
cat salary | awk ‘NR == 1 {printf “%5s %5s %5s %5s %5s\n”, $1, $2, $3, $4, “Total”} NR >= 2 {total = $2 + $3 + $4 ; printf “%5s %5d %5d %5d %5d\n”, $1, $2, $3, $4, total}’ // 看来打印的格式, 跟 c 语言相通, 另外, 所有的动作都在 {} 这个大括号内, 如果大括号内有多个命令可以使用; 分号来分隔, 与bash 不同的是, awk 中的变量可以直接使用, 而不用变量符号 $.
香港系统编译时, 也可以使用如下命令来进行修改, 编译的文件中, 主要的目的就是去掉空白行和前面注释的行. 那么可以这么进行
cat compileFile | sed ‘/^$/d’| grep ‘^[^#]’| awk ‘{}’ 其中 sed 是去掉空白行, grep 是去掉前边带注释的. awk 是直接编译文件, 注意这里的 sed 使用正则表达式时要加上 // 两个双斜线, 而grep 可以直接使用正则表达式
另外, 关于 awk 'begin{动作} end{动作}' begin 的动作表示的是读取文档之前的动作, end的动作表示的是读取文档之后的动作.