文件空行处理

1. 在文件中的每一行后面添加一个空行。

sed 'G' test.txt

解释: Get命令是将保留空间的内容取出,并添加到当前模式空间的内容之后(添加一行)。当保留空间为空时,效果为往模式空间添加一行空行。

2. 保证文件中的每一行后面都有一行空行。和1不同的是,如果文件中本身包含空行,则合并成一行。

sed '/^$/d;G' test.txt

解释:首先删除空行,再添加一行空行。

3. 删除偶数行

sed 'n;d' test.txt

解释:n的意思读入下一行,并且输出当前行。当n读入下一行之后,用d将其删除。

4. 在匹配regex的行之前添加空行

sed '/regex/{x;p;x}' test.txt

解释:x的意思是交换保留空间和模式空间的内容,首先保留空间为空,首次交换并用p打印空行;接着将原有内容交换回来,执行到命令末尾,自动输出模式空间的内容。

5. 在匹配regex的行之后添加空行

sed '/regex/G' test.txt

解释:参考1

6. 在匹配regex的行之前和之后都添加空行

sed '/regex/{x;p;x;G;}' test.txt

解释:参考4、5

7. 每五行后添加一行空行

sed 'n;n;n;n;G'

或者

sed '0~5G' test.txt

解释:很简单,每次读5行,再添加一个空行。第二种方法利用了GNU Sed的功能 addr~step,查看man sed。

文件行号处理

1. 给每一行添加行号,并且行号与行的非空白内容之间以制表符(t)分隔(保证左对齐)

类似:

1   aaa
20 aaa

相应的命令如下:

sed '=' test.txt | sed 'N;s/s*ns*/t/'

解释:首先要取出并打印行号,可以用=命令打印行号,但是此时行号与行内容不在同一行输出,因此需要将标准输出重定向再次使用sed命令处理。使用Next命令读入下一行,并将n(包括多余的空白)替换成一个制表符(t),再默认输出打印。准确地说,这里使用了两条sed命令。

2. 给每一行添加行号,并且行号与行的非空白内容之间以制表符(t)分隔(保证右对齐)

类似:(假设行号最多是3位数)

  1  aaa
20 aaa
123 aaa

相应的命令如下:

sed '=' test.txt | sed 'N; s/^/  /;s/ *([ 0-9]{3})s*ns*/1t/'

解释:前面同1,这里只介绍后面这部分:s/^/ /;s/ *([ 0-9]{3})s*ns*/1t/
这里首先在行首插入两个空格,然后将空格与后面的行号(数字)部分,只保留三个字符。最后将回车与多余的空白替换成制表符。

3. 给文件每一行加上行号,但是仅当行非空时才打印行号。

sed '/./=' test.txt | sed '/./N; s/s*ns*/t/'

解释:在sed中.不匹配n,因此用/./匹配非空行,其它同1。 但是如果要处理空行(包含空白符等的行),则需要:

sed '/[^[:blank:]]/=' test.txt | sed '/[^[:blank:]]/N; s/n/t/'

4. 统计行数

sed -n '$=' test.txt

解释:使用-n阻止默认输出,并只在最后一行的时候打印行号。

文本内容转换和替换

1. 在Unix环境下,转换DOS换行符为Unix格式

sed 's/^M//' test.txt

解释:^M的键入方法,按住ctrl+v再敲回车。 这种处理和环境依赖性比较大,不是非常统一,这里只介绍一种。

2. 删除行首和行尾空白

sed 's/^[[:blank:]]*|[[:blank:]]*$//' test.txt

解释:这里再次用到了posix字符组,不多解释。

3. 对每一行按照79列宽处理, 保持右对齐
类似

...................a
.................bba
................cccc

(超出的部分不处理)

sed -e ':a' -e 's/^.{1,78}$/ &/;ta' test.txt

解释: 对单个命令本身不解释了,这里用到了标签、跳转、替换等命令。 替换过程对不小于79列宽的行处理,在行首插入一个空格,直到等于79列宽为止,自动
输出。

4. 对每一行按照79列宽处理,保持居中。

sed -e ':a' -e 's/^.{1,77}$/ & /; ta' test.txt

解释:同3

5. 在每一行用bar替换foo

a. sed 's/foo/bar/' test.txt
b. sed 's/foo/bar/4' test.txt
c. sed 's/foo/bar/g' test.txt
d. sed 's/(.*)foo(.*foo)/1bar2/ test.txt
e. sed 's/(.*)foo/1bar/' test.txt

解释:a在一行中只替换一次(首次出现);b替换第四次出现;c全局替换;d替换倒数第二个匹配;e替换最后一个匹配 。

6. 在包含或者不包含baz的行中替换foo为bar

sed '/baz/s/foo/bar/g' test.txt
sed '/baz/!s/foo/bar/g' test.txt

7. 反转文件行的顺序(类似tac命令,即从最后一行到第一行的顺序打印)

sed '1!G;h;$!d' test.txt

解释:首先1!G表示将除第一行之外,都先从保留空间取出内容并追加到模式空间的最后;h表示将模式空间的内容全部覆盖到保留空间;然后 $!d表示将除最后一行之外的,都要将模式空间清除,并从头开始(不打印)。这些命令合起来就是,首先将一行的内容拷贝到临时缓冲区(保留空间),然后清除当前行(不打印),再读入下一行并从缓冲区取会保存的内容,因此行的顺序就颠倒了。

8. 反转文件中每一行的字符顺序(类似rev命令)

sed '/n/!G;s/(.)(.*n)/&21/;//D;s/.//'

解释:首先解释一下这里使用到的一些特殊语法,//D,//为无内容,这是一种简写情况,默认使用上一次使用的正则表达式,这里就是(.)(.*n),因此等价于/(.)(.*n)/D。这条sed命令中过程是这样的,首先该行如果不包含回车,则在末尾添加一个,对应命令中的/n/!G;然后开始替换,目的是把当前最前面的字母放到后面。

例如123n变成123n23n1;23n1变成23n3n21。然后使用D命令删除第一行的内容。最后一个替换去掉首字符。该例子可以自己使用一个简单的例子演练一遍就清楚了。

9. 将两行合并成一行(类似paste命令)

sed '$!N;s/n/ /' test.txt

解释:$!N表示除最后一行外,其它每行在读入的时候,都将下一行读进来添加到后面。接着用替换命令替换回车为空格。如果$!N改成N在这里不会出现问题,但是要记住的是,当到最后一行时,执行N命令将不会再读入新行,结果是sed退出。不会执行接下来的命令。

10. 如果一行以“”结束,则合并下一行内容到当前行之后。

sed -e ':a' -e '/$/N; s/n/ /; ta' test.txt

解释:同8类似,但是要考虑合并多行,因此需要做循环处理,这里使用标签来达到这个目的。

11. 如果一行以等号开始,则合并这一行至上一行,并替换等号为空格

sed -e ':a' -e '$!N;s/n=/ /;ta;P;D' test.txt

解释:同9类似,不过这里要读入下一行之后,判断'n='则替换成空格, 如果替换成功,则继续读入下一行(标签跳转);否则, 打印并删除模式空间中的第一行。
D命令不会导入新的行读入。

12. 给数字串加逗号,例如把“1234567”变成“1,234,567”

sed -e ':a' -e 's/([0-9])([0-9]{3})($|,)/1,2/;ta' test.txt

或者

sed -e ':a' -e 's/(.*[0-9])([0-9]{3})/1,2/;ta' test.txt

解释:这里要使用标签进行循环处理,关键点在正则表达式的书写上。第二种写法更加简练。

13. 给带有小数点和铅的数字加上逗号

sed ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/12,3/g;ta' test.txt

或者

sed ':a;s/^(-?[0-9]+)([0-9]{3})/1,2/g;ta' test.txt

解释:同11,要注意负号和小数点,因此要加上开始标记^和-。

选择性输出行

1. 打印一个文件的前10行(类似head命令)

sed -n '1,10p' test.txt

或者

sed '10q' test.txt

解释:显然第二种方法比第一种方法效率高。q退出命令,表明在第10行的时候自动退出,不再读入新的输入行。

2. 打印一个文件的第一行。

sed 'q' test.txt

解释:同上,在读入第一行之后就退出,但是仍打印第一行的内容。

3. 打印一个文件的倒数10行(类似tail命令)

sed ':a;$q;N;11,$D;ba'

解释:如果只看 ':a;$q;N;ba',效果就是一直将下一行追加到模式空间,最后达到最后一行的时候退出,并打印模式空间的内容。但是当变成':a;$q;N;11,$D;ba',11,$D表示如果行超过10行,则将模式空间的第一行删除,同时ba跳转到开头,再次读入下一行,保持模式空间的行数在10行。这样看起来就是模式空间的最前面的一行被删除,同时将新的一行追加到末尾处,当循环结束时,模式空间中保存的就是文件的最后10行。

4. 打印一个文件的倒数两行(类似tail -2)

sed ':a;$q;N;3,$D;ba'

或者

sed '$!N;$!D' test.txt

解释:第一种方法同3一样。第二种方法,$!的意思是不在最后一行上执行命令。N命令不解释,D命令是删除模式空间的第一行,并且跳转到命令开头重新执行,并且当模式空间仍有内容时,不读入新的输入行。这一句的意思透露出两点:
1) D命令之后的命令不会执行,而是跳转到开头,同时也不会自动输出当前模式空间的内容。
2) 模式空间不为空,则不会自动读入下一行的数据,除非使用N命令读入下一行。
因此,$!N;$!D,将下一行读入模式空间,并且将模式空间的第一行删除,除非遇到最后一行,因此当循环结束时,模式空间中包含倒数两行,完成要求,打印输出。

5. 打印一个文件的最后一行(类似tail -1)

sed ':a;$q;N;2,$D;ba' test.txt

或者

sed -n '$p' test.txt

或者

sed '$!d' test.txt

6. 打印匹配“regex”行(类似grep)

sed -n '/regex/p' test.txt

或者

sed '/regex/!d' test.txt

解释:同5类似

7. 打印不匹配“regex”行(类似grep -v)

sed -n '/regex/!p' test.txt

或者

sed '/regex/d' test.txt

解释:同6。

8. 打印匹配“regex”之前的那一行。

sed -n '$!N;/regex/!D;/regex/P'

或者

sed -n '/regex/{g;1!p;};h'

解释:第一方法理解起来比较简单,读入下一行到模式空间,并且判断是否包含regex,如果匹配,则打印模式空间中的第一行,如果不匹配,则删除模式空间的第一行,循环处理。(这种方法有问题吗?)
第二种方法,如果没遇到匹配行,则将当前行拷贝到保持空间,然后读入下一行,如果匹配,则将保存的行从保持空间中提取到模式空间,并且打印(假如第一行就匹配则不打印)。

9. 打印奇数行

sed -n 'N;P' test.txt

或者

sed -n '1~2p' test.xt

解释:第一种方法,N读入下一行到模式空间,P打印模式空间中的第一行,然后自动输出被关闭,进入下一次循环,重新读入新的一行到模式空间(自动读入新行,非N,因此模式空间的内容被清除再读入新行),再执行N;P,同样打印模式空间的第一行。效果等同于打印奇数行。第二种方法,比较简单,不过用到GNU Sed的特殊地址表示方法,addr~step,因此只在1,3,5,7等奇数行才打印行的内容。

10. 打印匹配“regex”那一行的后一行。

sed -n '/regex/{n;p}' test.txt

解释:如果找到匹配的行,则读取下一行,并且打印输出。

11. 打印匹配“regex”那一行的前后一行,并且打印匹配行的行号(类似grep -A1 -B1)

sed -n '/regex/{=;x;1!p;g;$!N;p;D;}; h' test.txt

解释: 如果不匹配,则先把该行保存到保持空间暂时记录下来;如果找到匹配行,则打印该行的等号,并且将模式空间的内容和保持空间的内容交换,随即打印模式空间的内容(第一行除外,同10);交换之后,再次将保持空间的内容恢复到模式空间(即当前匹配行),再读入下一行(注意$!N),打印模式空间的所有内容(非P),打印完之后,清除模式空间的第一行的内容。进入下一个循环。注意此时,保持空间同样保存着当前的输入行。

12. 假设段落以空行分隔,打印包含“regex”的段落。

sed '/./{H;$!d};x;/regex/!d' test.txt 
sed '/./{1h;1!H;$!d};x;/regex/!d' test.txt 

解释:思路很简单,首先将读入段落的内容,并依次将段落的第一行追加到保持空间备份,然后在保持空间中查找匹配单词。但是第一种方法的输出结果会在开始处多一个空行,第二种方法的目的是去掉多输出的一个空行。

13. 打印长于65个字符的行

sed -n '/^.{65}/p' test.txt

解释:正则表达式的应用。

14. 打印第52行

sed '52q;d' test.txt

解释:效率比一般方法高

15. 从第三行开始,每隔7行打印机一行

sed -n '3~7p' test.txt
sed -n '3,${p;n;n;n;n;n;n;}' test.txt

解释:比较简单

选择性删除某些行

1. 删除文件中连续并且重复的行,只保留第一行(类似uniq命令)

sed -n "$!N;/^(.*)n1$/!P;D' test.txt

解释:读入下一行,然后用正则判断两行是否一样,如果一样,则不打印,并且删除同样行中的第一行,再循环处理。

2. 删除文件中重复的,但不连续的行,注意不要溢出保持空间的缓冲区大小。
不知道

3. 删除一个文件中前10行

sed '1,10d' test.txt

解释:比较简单

4. 删除一个文件中最后1行

sed '$d' test.txt

5. 删除一个文件中最后2行

sed 'N;$!P;$!D;$d' test.txt

解释:使用N读入一行,并且如果新读入的下一行不是最后一行,则打印模式空间中的第一行,并且删除;如果新读入的一行是文件的最后一行,则删除模式空间中的所有内容(即倒数两行)。

6. 删除一个文件中最后10行;

sed ':a;$d;N;11,${P;D};ba' test.txt
sed ':a;$d;N;2,10ba;P;D' test.txt
sed -n ':a;1,10!{P;N;D};N;ba'

解释:第一种方法参考前面的打印文件的最后10行内容。第二种方法,首先不停读入下一行的内容,直到读入第11行,此时模式空间中包含11行,打印第一行的内容并删除,然后判断最后读入的那一行是不是最后一行,如果是,则删除模式空间中的内容(一共10行,即倒数10行);如果不是,则继续读入下一行,打印模式空间中的第一行并删除。循环直到最后一行为止。第一种方法,首先将读入前10行的内容,如果读到第10行之后(11行开始),首先打印模式空间的第一行,并读入下一行,再删除第一行,循环处理;始终保证模式空间中包含10行的内容,当在最后一行之后,再读新行会导致sed退出,并打印模式空间的内容。

7. 每8行删除1行

sed '0~8d' test.txt

解释:比较简单。

8. 删除所有空行

sed '/^$/d' test.txt

或者

sed '/./!d' test.txt

解释:都比较简单,第一个匹配空行,第二个匹配非空行。

9. 压缩文件中的连续空行为一行,包括文件开头和结尾(类似cat -s)

sed '/^$/N;/n$/D' test.txt

解释:遇到空行,则继续读入下一行,如果读入的一行依然是空行,则删除第一行(空行),循环处理。

10. 删除文件中的连续空行,但保留前两个空行

sed '/^$/N;/n$/N;//D' test.txt 

解释:同9,不过不是压缩空行为一行,而是两行,因此在9的基础上再加一步,//D中正则为空,默认使用上次的正则表达式。

11. 删除文件开头的空行

sed '/./, $!d' test.txt

解释:删除第一行非空行之前的所有空行。

12. 删除文件结尾的所有空行

sed ':a;/^n*$/{$d;N;ba}' test.txt

解释:如果碰到一个空行,如果不是最后一行,则继续读入下一行,跳到开头,判断模式空间内是否全是空行。如果读到最后一行,而且,模式空间内的内容都是空行,则删除,这意味着删除了所有结尾处的空行。

13. 删除每个段落的最后一行

sed -n '/^$/{p;h;};/./{x;/./p}' test.txt

解释:如果遇到空行,则直接打印,并且将空行保存到保持空间,这样会覆盖空行的上一行内容,如果上一行不为空行,内容就不打印了,而如果上一行是空行,因为之前已经打印了,所以这里不会有影响;如果不是空行,则交换保持空间和模式空间的内容,保持空间保存的是上一行的内容,如果上一行不是空行,则打印。

转载请注明转自: 团子的小窝 , 本文固定链接: sed1line 笔记

sed用例的更多相关文章

  1. linux之awk、sed命令

    总结: 两个命令的正则表达式都用''单引号进行区分. 输出变量名用单引号,输出变量值用双引号,这个在bash脚本里一般是通用的. 在bash脚本里要使用变量值,都要加上双引号 awk用法: 参考网址: ...

  2. sed命令拷屏

    http://blog.sina.com.cn/s/blog_45497dfa0100w6r3.html  sed样例较多,可以参考 http://blog.sina.com.cn/s/blog_6d ...

  3. sed修炼系列(一):花拳绣腿之入门篇

    本文为花拳绣腿招式入门篇,主要目的是入门,为看懂sed修炼系列(二):武功心法做准备.虽然是入门篇,只介绍了基本工作机制以及一些选项和命令,但其中仍然包括了很多sed的工作机制细节.对比网上各sed相 ...

  4. sed 之 N D P

    sed的N,D,P 是用于多行模式空间的命令,分别对应于n,d,p n & N: n(next)输出模式空间的内容,然后读取新的输入行,n命令不创建多行模式空间:N(Next)通过读取新的输入 ...

  5. shell的编程结构体

    本文目录: 1.1 shell函数 1.2 条件结构:if 1.3 条件结构:case 1.4 条件结构:select 1.5 循环结构:for 1.6 循环结构:while 1.7 循环结构:unt ...

  6. shell中while循环的陷阱

    在写while循环的时候,发现了一个问题,在while循环内部对变量赋值.定义变量.数组定义等等环境,在循环外面失效. 一个简单的测试脚本如下: #!/bin/bash echo "abc ...

  7. shell的编程结构体(函数、条件结构、循环结构)

    bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 1.1 shell函数 在shell中,函数可以被当作命令一样 ...

  8. sed实例精解--例说sed完整版

    原文地址:sed实例精解--例说sed完整版 作者:xiaozhenggang 最近在学习shell,怕学了后面忘了前面的就把学习和实验的过程记录下来了.这里是关于sed的,前面有三四篇分开的,现在都 ...

  9. sed 技巧一例:特定位置插入

    通过一例子熟悉 sed 的运用 下面命令是在修改 ~/fs/install/nzos.conf 文件, 并在 env 第一次出现的地方再添加一行 env LXC_EXTRA_PORT=5556 sed ...

随机推荐

  1. Activity后台运行一段时间回来crash问题的分析与解决

    最近做项目的时候碰到一个棘手的问题,花了不少时间才找到原因并解决.特此记录这个被我踩过的坑,希望其他朋友遇到此问题不要调到这坑里去了. 问题描述: 1.背景:我的app中某个界面的Activity是继 ...

  2. Maven full settings.xml

    <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Soft ...

  3. Apex Design Patterns

    Apex allows you to build just about any custom solution on the Force.com platform. But what are the ...

  4. VMware Workstation安装RedHat Linux 9

    RedHatLinux是目前世界上使用最多的Linux操作系统.因为它具备最好的图形界面无论是安装.配置还是使用都十分方便.下面我将介绍使用VMware Workstation安装RedHat Lin ...

  5. 构建自己的NSZombie

    当开启 xcode zombie 选项,发送消息到一个被  "释放了的对象"  时 ObjZomies *oz = [[ObjZomies alloc] init]; oz.nam ...

  6. Visual Studio 2008 使用 WinCE 5.0 Emulator

    1. 簡介 由於 Visua Studio 2008 與 WinCE 5.0 Emulator 並沒有完全整合,因此想要測試我們所開發的 Windows CE 程式,需透過設定,將我們所開發的程式丟到 ...

  7. C#版Windows服务安装卸载小工具-附源码

    前言 在我们的工作中,经常遇到Windows服务的安装和卸载,在之前公司也普写过一个WinForm程序选择安装路径,这次再来个小巧灵活的控制台程序,不用再选择,只需放到需要安装服务的目录中运行就可以实 ...

  8. webpack处理Img标签路径的几种情况

    在使用webpack过程中遇到这个问题,各种搜索遇到此问题的还真不少,但都没有一个完整的说明. 后来研究下,图片除了路径替换还是就是图片做优化主是小于一定大小的通过转 base64 inline方式减 ...

  9. How To Create a Personal Balance Sheet

    Calculating your personal net worth is the best way to know exactly what your starting point is, in ...

  10. vim中多标签和多窗口的使用

    用vim进行编辑的时候常常因为要编辑多个文件或者是编辑一个文件要参考其他文件而烦恼,这里介绍两种方法: 1.多标签 直接在编辑的时候输入: vim -p 要编辑的文件名 如vim -p * 就是编辑当 ...