Linux中sed和awk的使用及其相关实例解析

如果对实例中涉及的相关Linux命令不了解,可以参考:Linux下sed,awk,grep,cut,find等常用命令介绍

在每一行后面增加一空行

sed方法:

sed G express

关于sed的几个命令参数: G 获得内存缓冲区的内容(此时内存缓冲区是空的),并追加到当前模板块文本的后面。

awk方法:

awk ‘{print $0 “\n”}’ express

关于awk:

awk是一种用于处理文本的编程语言工具。AWK 实用工具的语言在很多方面类似于 shell 编程语言,尽管 AWK 具有完全属于其本身的语法。在最初创造 AWK 时,其目的是用于文本处理,并且这种语言的基础是,只要在输入数据中有模式匹配,就执行一系列指令。该实用工具扫描文件中的每一行,查找与命令行中所给定 内容相匹配的模式。如果发现匹配内容,则进行下一个编程步骤。如果找不到匹配内容,则继续处理下一行。

awk命令的语法

awk ‘{pattern + action}’ {filenames}

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。

$0,关于awk的字段

实用工具将每个输入行分为记录和字段。记录是单行的输入,而每条记录包含若干字段。默认的字段分隔符是空格或制表符,而记录的分隔符是换行。虽然在默认情况下将制表符和空格都看作字段分隔符(多个空格仍然作为一个分隔符),但是可以将分隔符从空格改为任何其它字符。

当 AWK 读取输入内容时,整条记录被分配给变量 $0。每个字段以字段分隔符分开,被分配给变量 $1、$2、$3 等等。一行在本质上可以包含无数个字段,通过字段号来访问每个字段。

所以print $0 的意思是打印当前处理的整行数据,”\n”表示换行。

设置文本中每一行后面有且只有一空行

sed方法:

sed ‘/^$/d;G’ express

sed相关的命令参数: d 从模板块(Pattern space)位置删除行,详细解释见文章开始提供的链接。 G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。 ‘;’号: 如果在一行中有多个命令,要用分号隔开。 相关解释: /^$/d;表示遇到空行,则删除,d命令执行后不会继续执行下面的命令G,而是直接读入下一行重新执行’/^$/d;G’进行处理。直到匹配到不是空行才执行G命令把hold space中的内容(此时为空)追加到文本的后面,然后默认输出。

awk方法:

awk ‘!/^$/{printf(“%s\n\n”,$0)}’ express

关于awk知识点: 使用模式:

通过包含一个必须匹配的模式,您可以选择只对特定的记录而不是所有的记录进行操作。模式匹配的最简单形式是搜索,其中要匹配的项目被包含在斜线 (/pattern/) 中。

相关解释: !/^$/即是不是空行的 printf(“,$0)表示输出当前处理的整行字符串,输出字符的格式””%s\n\n”表示输出字符串,然后执行两个换行即空一行。

在每行后面增加2行空行

sed方法:

sed ‘/^$/d;G;G’ express

sed相关的命令参数: d 从模板块(Pattern space)位置删除行。 G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。 相关解释: sed ‘/^$/d;G;G’ /^$/表示匹配到空行时进行处理,d表示删除,即是遇到空行就删除,然后读取下一行处理,直到读取到的不是空行为止才执行下面的G;G;获得内存缓冲区的内容,并追加到当前模板块文本的后面,这里的内存缓冲区中的内容此时为空。

awk方法:

awk ‘!/^$/{printf(“%s\n\n\n”,$0)}’ express

相关解释: awk ‘!/^$/{printf(“%s\n\n\n”,$0)}’表示查找到不是空行的就进行输出printf(“%s\n\n\n”,$0),输出$0表示当前处理的整行字符,”%s\n\n\n”表示输出字符串,三个\n表示空两行。

删除所有偶数行

sed方法:

sed ‘n;d’ express

sed相关的命令参数: n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。 -n, –quiet, –silent 安静模式,取消默认输出。 d 从模式空间(Pattern space)位置删除行。 相关解释: sed ‘n;d’ 执行n时会首先输出当前处理行,然后读取下一行,并使用d命令删除。

awk方法:

awk ‘NR%2!=0{print $0}’ express

awk相关的命令参数: NR 表示awk开始执行程序后所读取的数据行数 相关解释: ‘NR%2!=2’表示不是偶数行

在匹配The的行前插入空行

sed方法:

sed ‘/The/{x;p;x}’ express

sed相关的命令参数: x 交换pattern和hold space p 打印pattern space 相关解释: sed ‘/The/{x;p;x}’第一个x首先交换,这时pattern space为空,hold space为匹配/xx/这一行的内容,交换后使用p输出模式空间中的内容为空行,然后再换回来,保持pattern space为空,为下一次处理做准备。

awk方法:

awk ‘{if (/The/) printf(“\n%s\n”,$0); else print $0}’ express

awk相关命令参数: 条件语句 awk中的条件语句是从C语言中借鉴过来的,可控制程序的流程。 格式: {if (expression){ statement; statement; … } } 相关解释: awk ‘{if (/The/) printf(“\n%s\n”,$0);表示匹配到The的行,就使用printf函数输出$0表示整行字符串,输出的格式为”\n%s\n”表示先换行再输出,然后再换行,表示The之前空一行。

输出行号,行号和正文间加冒号

sed方法:

sed = express | sed ‘N;s/\n/:/‘

sed相关命令参数: N 追加下一个输入行到模式空间后面并在二者间嵌入一个“\n”,改变当前行号码。 = 打印当前行号 s/re/string 用string替代正则表达式re sed = express 输出行号和行的内容,行号和内容分两行输出 sed ‘N;s/\n/:/‘N读取下一行(行的内容)在两行之间插入\n,然后再使用s/re/string把\n替换成“:”

awk方法:

awk ‘{printf(“%d:%s\n”,NR,$0)}’ express

NR 表示awk开始执行程序后所读取的数据行数. $0 表示当前处理的整行数据 printf(“%d:%s\n”,NR,$0) 输出,格式为:十进制有符号整数输出NR行号 :当前处理的行所包含的字符串。

对文件中的所有非空行编号

sed方法:

sed ‘/./=’ express | sed ‘/./N;s/\n/:/‘

sed相关命令参数: s/re/string 用string替代正则表达式re N 追加下一个输入行到模式空间后面并在二者间嵌入一个“\n”,改变当前行号码。 = 打印当前行号 . 匹配一个非换行符的字符 相关解释: ‘/./=’表示第一个字符是非换行字符的输出行号,sed ‘/./N;s/\n/:/‘中N读取下一行(行的内容)并在两行之间插入\n,然后再使用s/re/string把\n替换成“:”

awk方法:

awk ‘{if (/./) printf(“%d:%s\n”,NR,$0);else print $0}’ express

awk相关命令参数: NR 表示awk开始执行程序后所读取的数据行数 相关解释: printf(“%d:%s\n”,NR,$0) 输出,格式为:十进制有符号整数 :当前处理的行所包含的字符串 整个语句表示:如果不是空行,则调用printf函数以“数字:字符串+换行”的形式输出当前处理行号了整行内容,否则,直接输出当前处理的整行内容。

计算行号(模拟 “wc -l”)

sed方法:

sed -n ‘$=’ express

关于WC命令: wc就是word count(数字数)的缩写,通常利用Linux的wc命令和其他命令结合来计算行和其他信息。在Linux下用wc进行计数。返回文件的行数、字数、字节数等。 wc -m filename:显示一个文件的字符数 wc -l filename:显示一个文件的行数 wc -L filename:显示一个文件中的最长行的长度 wc -w filename:显示一个文件的字数 sed相关的命令参数: -n, –quiet, –silent 安静模式,取消默认输出。 $ 锚定行的结束 如:/sed$/匹配所有以sed结尾的行。 = 打印当前行号 相关解释: $=表示打印最后一行的行号,-n表示安静模式,不会输出其他行的相关内容

awk方法:

awk ‘END {print NR}’ express

awk相关的知识点: BEGIN和END 在awk 中两个特别的表达式,BEGIN和END,这两者都可用于pattern中,提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。 所以awk ‘END {print NR}’也就是在读取到最后一行之后,才输出对于的行号,也就是输出该文件的行数。

模拟dos2unix

关于dos2unix命令 dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter)。DOS下的文本文件是以\r\n作为断行标志的,表示成十六进制就是0D 0A。而Unix下的文本文件是以\n作为断行标志的,表示成十六进制就是 0A。DOS格式的文本文件在Linux底下,用较低版本的vi打开时行尾会显示^M,而且很多命令都无法很好的处理这种格式的文件,如果是个shell脚本,。而Unix格式的文本文件在Windows下用Notepad打开时会拼在一起显示。因此产生了两种格式文件相互转换的需求,对应的将UNIX格式文本文件转成成DOS格式的是unix2dos命令。 所以实现dos2unix的关键就是把dos中多余的\r去掉。

sed方法:

sed ‘s/\r//g’ expressdos >expressdos1

模拟unix2dos:
sed ‘s/$/\r/‘ expressdos > expressdos1

sed ‘s/$/\x0d/‘ expressdos >expressdos1

sed相关命令参数: s/re/string 用string替代正则表达式re 相关解释: 使用s/re/string替换多余的\r,然后默认输出模式空间中的数据

awk方法:

awk ‘gsub(/\r/,””){print $0}’ express > express2

awk相关知识点: gsub(r,s,t) 在字符串t中用字符串s和正则表达式r匹配的所有字符串。返回值是替换的个数。如果没有给出t,默认是$0 相关解释: 使用gsub把\r替换成””,然后再输出当前处理的整行字符串

将所有good改为bad并打印且只打印该行

sed方法:

sed -n ‘s/good/bad/‘p express

sed相关命令参数: s/re/string 用string替代正则表达式re -n, –quiet, –silent 安静模式,取消默认输出。 p 打印模式空间的行,通常 p 会与参数 sed -n 一起使用。 相关解释: 使用安静模式取消默认输出,s/good/bad表示如果匹配到good,则替换为bad,并打印输出。

awk方法:

awk ‘gsub(“good”,”bad”){print $0}’ express

相关解释: 使用gsub把good替换成bad,接着打印整行

将包含is的行的good改为bad并打印且只打印该行

sed方法:

sed -n ‘/is/{/good/{s/good/bad/g;p}}’ express

sed相关命令参数: -n 安静模式,取消默认输出。 g 表示行内全面替换,当前处理行进行全局替换。 相关解释: -n使用安静模式,/is/匹配包含is的行,/good/匹配包含is的行中包含good的行,s/good/bad/g,把改行所有的good都替换成bad,然后使用p输出该行。

awk方法:

awk ‘{if ($0~/is/ && $0~/good/) {gsub(/good/,”bad”); print $0}}’ express

相关解释: $0~/is/表示使用第0个域匹配/is/正则表达式,第0个域保存的即是当前处理的整行数据。 ($0~/is/ && $0~/good/)就是如果当前处理的整行同时包含is和good的话就执行if里面的语句。if里面的语句使用gsub把匹配的good替换成bad,然后输出当前行。

将不包含is的行的good改为bad并打印且只打印该行

sed方法:

sed -n ‘/is/!{/good/{s/good/bad/g;p}}’ express

sed相关命令参数: ! 表示后面的命令对所有没有被选定的行发生作用。 相关解释: -n使用安静模式,/is/匹配包含is的行,然后使用!取得没有被匹配到的行进行操作,/good/表示从没有被匹配到的行中匹配包含good的行,s/good/bad/g,把改行所有的good都替换成bad,然后使用p输出该行。

awk方法:

awk ‘{if ($0!~/is/ && $0~/good/) {gsub(/good/,”bad”); print $0}}’ express

相关解释: $0!~/is/表示使用第0个域匹配/is/正则表达式,找出匹配不到的行继续进行处理。第0个域保存的即是当前处理的整行数据。 ($0!~/is/ && $0~/good/)就是如果当前处理的整行不包含is和包含good的话就执行if里面的语句。if里面的语句使用gsub把匹配的good替换成bad,然后输出当前行。

显示文件中的前10行 (模拟“head”)

关于head命令: head是查看文件默认前10行

sed方法:

sed 10q express

相关解释: q表示退出sed,10q表示处理到第10行的时候退出sed。

awk方法:

awk ‘{if (NR<11) print $0}’ express

awk相关的命令参数: NR 表示awk开始执行程序后所读取的数据行数

在每5行后增加一空白行

sed方法:

sed ‘n;n;n;n;G’ express

sed相关命令参数: n 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。 G 获得内存缓冲区(hold space)的内容,并追加到当前模式空间文本的后面。 相关解释: n;n;n;n;G的执行4个n命令读取下一行,每次读取之前都先输出当前的处理行。然后把hold space(这时为空)中的内容追加到模式空间的后面,相当于增加一空白行。

awk方法:

awk ‘{if (NR%5!=0) print $0;else printf(“%s\n\n”,$0)}’ express

awk相关的命令参数: NR 表示awk开始执行程序后所读取的数据行数. 相关解释: 如果读取的数据行数不是5的倍数,则直接打印整行,如果是5的倍数,则调用printf(“%s\n\n”,$0)函数打印整行和一个空行。

倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)

关于tac命令: 把文件内容反过来显示,文件内容的最后一行先显示,第一行最后显示。

sed方法:

sed ‘1!G;h;$!d’ express

sed相关方法: G 获得内存缓冲区的内容,并追加到当前模板块文本的后面。 h 拷贝模板块的内容到内存中的缓冲区。 d 从模板块(Pattern space)位置删除行。 ! 表示后面的命令对所有没有被选定的行发生作用。 $ 锚定行的结束 如:/sed$/匹配所有以sed结尾的行。这里表示文件最后一行。 1 表示文件第一行 相关解释: 第一行的时候 1!G:在处理第一行的时候不把缓冲内容添加到 当前处理行的末尾(因为你处理第一行的时候,缓冲还为空呢) h:这个时候把第一行的内容(1)放到缓冲区 $!d:因为不是最后一行,所以删除,不打印出来 第二行的时候 1!G:此时1!G成立,把上一次保存的缓冲区内容(1)放到当前行(2)的末尾,第二行变成了(21) h:这个时候把第二行的内容(21)放到缓冲区 $!d:因为不是最后一行,所以删除,不打印出来 第三行的时候 1!G:因为是第三行,所以1!G成立,则把上一次(第二行)保存的缓冲区内容(21)放到当前行(3)的末尾,第二行变成了(321) h:这个时候把第三行的内容(321)放到缓冲区 $!d:因为不是最后一行,所以删除,不打印出来 这样直到处理到最后一行的时候: 1!G:此时1!G成立,把上(n-1)一次保存的缓冲区内容([n-1]…321)放到当前行(n)的末尾,该行变成了(n…321) h:这个时候把第n行的内容(n…321)放到缓冲区 $!d:因为是最后一行,所以不删除,打印出第六行内容 n[n-1]…321

awk方法:

awk ‘{A[i++]=$0}END{for(j=i-1;j>=0;j–)print A[j]}’ express

awk相关知识点: BEGIN和END 在awk 中两个特别的表达式,BEGIN和END,这两者都可用于pattern中,提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。任何在BEGIN之后列出的操作(在{}内)将在awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。 相关解释: 首先输入每行字都执行A[i++]=$0,即是把所有行的内容保存到A[i]数组中。直到处理完所有的行之后,继续质询END中的内容:for(j=i-1;j>=0;j–)print A[j],这里是吧A[i]中的元素倒序输出,即是倒置所有的行。

显示文件中的最后10行 (模拟“tail”)

sed方法:

sed -e :a -e ‘$q;N;11,$D;ba’ express

sed方法相关命令参数: -e 直接在指令列模式上进行 sed 的动作编辑,允许多台编辑。 :a 表示建立一个标签a b 跳转命令,这个命令是无条件跳转 ba表示跳转到标签a处 q 退出Sed。 N 追加下一个输入行到模板块后面并在二者间嵌入一个“\n”,改变当前行号码。 D 删除模板块的第一行。 11 表示文件第十一行 相关解释: 首先创建一个a标签,然后不断执行这段代码:$q;N;11,$D;ba,如果是最后一行则退出sed,否则继续循环,N读取下一行,读取模式空间的第11行,如果是最后一行则删除模式空间的第一行,继续跳到标签a处执行。

awk方法:

awk ‘{a[i++]=$0}END{if (i>10) for (j=i-10;j<i;j++) print a[j];else for (j=0;j<i;j++)print a[j]}’ express

相关解释: 使用{a[i++]=$0}把每行字符串赋给a[i]数组,然后判断数组大小是不是大于10 if (i>10),如果是则输入最后10个元素,否则直接输出所有的元素。

显示文件中的最后2行(模拟“tail -2”命令)

关于tail命令: tail [ -r ] [ -n Number ] [ File ] tail 命令从指定点开始将 File 参数指定的文件写到标准输出。如果没有指定文件,则会使用标准输入。 Number 变量 指定将多少单元写入标准输出。 Number 变量的值可以是正的或负的整数。如果值的前面有 +(加号),从文件开头 指定的单元数开始将文件写到标准输出。如果值的前面有 -(减号),则从文件末尾指定的单元数开始将文件写到 标准输出。如果值前面没有 +(加号)或 -(减号),那么从文件末尾指定的单元号开始读取文件。 tail -2即是输出最后两行。

sed方法:

sed ‘$!N;$!D’ express

sed相关命令参数: ! 表示后面的命令对所有没有被选定的行发生作用。 N 追加下一个输入行到模板块后面并在二者间嵌入一个“\n”,改变当前行号码。 D 删除模板块的第一行。 相关解释: $!表示如果不是最后一行则执行N命令读取下一行,$!D表示如果不是最后一行则删除第一行。注意:执行D命令之后,pattern space 内不添加下一笔数据, 而将剩下的数据重新执行sedscript 。也就是直接再次执行$!N命令,读入下一行。知道最后一行时就不执行D删除命令,此时patten space中有最后两行数据。

awk方法:

awk ‘{a[i++]=$0}END{if (i>2) for (j=i-2;j<i;j++) print a[j];else for (j=0;j<i;j++)print a[j]}’ express

相关解释:

a[i++]=$0命令保存所有行到a[i]数组中。处理完所有语句之后执行END里的内容。然后分两种情况输出:超过两条语句的使用a[i]数组输出最后两行,没有超过两句的,直接使用a[i]输出。

显示文件中的最后一行(模拟“tail -1”)

sed方法:

sed ‘N;D’ express

相关解释: N读取下一行,接着使用D删除第一行,此时patten space中只剩下后一行。注意:执行D命令之后,pattern space 内不添加下一笔数据, 而将剩下的数据重新执行sedscript 。也就是直接再次执行N命令,读入下一行,然后删除第一行。一直这样循环,直到最后一行,打印输出patten space中的内容,也就是最后一行的内容。

awk方法:

awk ‘END{print $0}’ express

相关解释: awk中处理完所有的语句后(这里没做处理),执行END里的内容,print $0,表示输出最后一次处理的整行信息,即最后一行的内容。

显示第9行

sed方法:

sed -n ‘9p’ express

sed相关命令参数: -n 安静模式,取消默认输出。 p 打印模式空间的行,通常 p 会与参数 sed -n 一起使用 9 表示文件第9行

awk方法:

awk ‘{if (NR==9) print $0}’ express

awk相关命令参数: NR 表示awk开始执行程序后所读取的数据行数

显示包含50个或以上字符的行

sed方法:

sed -n ‘/^.\{50,\}$/p’ express

sed相关的命令参数: -n 安静模式,取消默认输出。 p 打印模板块的行。 . 匹配一个非换行符的字符 相关解释: ‘/^.\{50\}$/p’ 表示匹配以非换行字符开始的50个以上的字符的行,然后使用p命令输出。

awk方法:

awk ‘{if (length($0)>=50) print $0}’ express

length(s)函数: 返回s长度

显示部分文本——从包含apple的行开始到最后一行结束

sed方法:

sed -n ‘/apple/,$p’ express

awk方法:

awk ‘BEGIN{p=1}{if ($0~/apple/ || p==0){p=0;print $0}}’ express

相关解释: 在处理语句之前,先执行BEGIN里面的语句,即让p=1。然后使用($0~/apple/ || p==0)判断正在处理的该行语句有没有apple,如果有,则让p=0,然后输出该行,由于此时p==0,所以条件总是成立,会把接下来到最后的语句全部输出。

显示通篇文档,除了从包含apple的行到包含google的行

sed方法:

sed ‘/apple/,/google/d’ express

相关解释: /apple/,/google/d表示匹配从包含apple的行到包含google的行,然后使用d全部删除。

awk方法:

awk ‘BEGIN{p=1}{if ($0!~/apple/ && p==1)print $0;else p=0;if ($0~/google/) p=1;}’ express

相关解释: 首先在BEGIN中给p赋初值1,然后依次处理每一条语句。如果没有匹配到apple并且p==1,则输出改行;否则p=0,直到匹配到google为止,才让p=1,继续输出。

arthinking wechat
欢迎关注itzhai公众号