[译]Unix sed实用教程第二篇–替换文件内容

上一节中-Unix sed实用教程第一篇–向文件中增加一行 学习了添加文件,本节讲解数据内容替换. 本节将使用sample1.txt文件作为示例,文件内容如下,都是些水果..: apple orange banana pappaya 1.向每一行的开头添加内容,这里我们添加“Fruit:” $ sed 's/^/Fruit: /' sample1.txt Fruit: apple Fruit: orange Fruit: banana Fruit: pappaya 解析:s代表substitution,也就是替换,s之后是要替换/匹配的内容,斜线/用来分隔s以及要替换的原始内容还有要替换的最终内容,而’^‘符号是说一个正则,用来匹配每一行的开头,匹配成功后在开头加上’Fruit:’。 2.向每一行的行尾添加内容 $ sed 's/$/ Fruit/' sample1.txt apple Fruit orange Fruit banana Fruit pappaya Fruit 注意,这里的$和上一节的$符号表示的意义不同,这里则是表示行尾. 3.如何替换指定的字符,这里将小写a替换成大写A $ sed 's/a/A/' sample1.txt Apple orAnge bAnana pAppaya 注意,仅仅将每一行的第一个a替换了,不是所有,本例表示替换单个字符,你可以替换一个单词都是可以的. 4.如何替换行内所有的字符,用A替换a $ sed 's/a/A/g' sample1.txt Apple orAnge bAnAnA pAppAyA 注意,只是加了一个g选项,g为global的简写,就是全局,全部的意思。 5.如何替换第二次出现的a? $ sed 's/a/A/2' sample1.txt apple orange banAna pappAya 不使用g,而是使用数字来表示行内第几次出现的a,结果如上 6.如何替换第二次之后的所有a呢? $ sed 's/a/A/2g' sample1.txt apple orange banAnA pappAyA 很好理解对吧。 7.如果只想替换第三行的a呢? $ sed '3s/a/A/g' sample1.txt apple orange bAnAnA pappaya 回想一下第一节,在执行命令之前,会判断当前address是否满足条件,3就是地址 8.想替换一个范围行内的数据呢 $ sed '1,3s/a/A/g' sample1.txt Apple orAnge bAnAnA pappaya 逗号隔开,即可 9.如何替换整行呢?比如用apple is a Fruit替换apple $ sed 's/.*/& is a Fruit/' sample1.txt apple is a Fruit orange is a Fruit banana is a Fruit pappaya is a Fruit 这里‘&’符号标识了模式匹配到的内容,而.*匹配了正行,.表示任意字符,*表示一个或多个,也就是匹配了整行,&因此就是整行内容,用来重命名一组文件的时候非常有用. 10.如何进行多个替换,比如用A替换a,用P替换p $ sed 's/a/A/g; s/p/P/g' sample1.txt APPle orAnge bAnAnA PAPPAyA 也就是用分号分开即可。或者也可以通过-e参数来做 $ sed -e 's/a/A/g' -e 's/p/P/g' sample1.txt APPle orAnge bAnAnA PAPPAyA -e 选项就是当需要替换多个的时候来用的。 ...

2013-08-09 · 1 min · bystander

[译]Unix sed实用教程第一篇--向文件中增加一行

Unix sed实用教程第一讲,本系列第一篇,有任何问题欢迎留言讨论。 sed 是unix中最重要的编辑器之一,注意,有之一..支持多种编辑任务,本文将实现题目的功能实例 假定我们有一额文本文件,叫做empFile,包含了员工名字和员工id,如下: Hilesh, 1001 Bharti, 1002 Aparna, 1003 Harshal, 1004 Keyur, 1005 1.如何通过sed给文件添加标题行-“Employee, EmpId” $ sed '1i Employee, EmpId' empFile Employee, EmpId Hilesh, 1001 Bharti, 1002 Aparna, 1003 Harshal, 1004 Keyur, 1005 解释:数字1,是说只对第一行执行操作,i代表在insert(熟悉vim的同学应该知道,i会在当前字符的前面插入,a是在后面插入),因此,1i就表示在将Employee, EmpId插入到第一行之前, 然后,有了标题行的文件仅仅会输出到标准输出,源文件内容并不会改变,如果需要更新源文件,可以使用重定向输出到一个临时文件,然后移动到原始文件。如果Unix系统的sed是GUN版本的,sed会有一个-i选项,可以直接实现更新源文件,(如何查看版本,终端下输入sed –version即可看到)下面先执行,再查看文件,发现已经多了标题行了 $ sed -i '1i Employee, EmpId' empFile $ cat empFile Employee, EmpId Hilesh, 1001 Bharti, 1002 Aparna, 1003 Harshal, 1004 Keyur, 1005 2.如何在标题行之后,也就是原始第一行之前添加一行横线–“—–” $ sed -i '1a ---------------' empFile $ cat empFile Employee, EmpId --------------- Hilesh, 1001 Bharti, 1002 Aparna, 1003 Harshal, 1004 Keyur, 1005 同1,中,1表示第一行,a表示append(附加),也就是说当读入第一行的时候在其之后添加一行,如果你使用2i作为命令也是正确的,就是指当读入第二行的时候,在其之前插入一行。 3.如何在文件尾部添加一行 $ sed -i '$a ---------------' empFile $ cat empFile Employee, EmpId --------------- Hilesh, 1001 Bharti, 1002 Aparna, 1003 Harshal, 1004 Keyur, 1005 --------------- 为了在文件尾部插入一行,如果使用之前的方法就需要知道总共有多少行,而$符号则直接指明了最后一行,因此$a表示在读入最后一行的时候,在后面插入一行 4.如何在指定的记录之后插入一条新纪录 假定我们的例子文件的内容现在是: Employee, EmpId --------------- Hilesh, 1001 Harshal, 1004 Keyur, 1005 --------------- 如果我想在Hilesh这个员工之后插入Bharti员工的信息,我这样做: $ sed -i '/Hilesh/a Bharti, 1002' empFile $ cat empFile Employee, EmpId --------------- Hilesh, 1001 Bharti, 1002 Harshal, 1004 Keyur, 1005 --------------- 注意看,我们这里已经不再使用数字或者其他表示行号的标识了,我们使用了一个模式(了解过正则表达式的朋友会比较熟悉,可以理解为某种规则- /Hilesh/a 这个命令表示对于每一行读入的内容,如果发现 /Hilesh/这个匹配,在该行之后插入一行,也就是说如果文件里有两行都是Hilesh员工,那么执行完上面的命令,将会附加两行内容,这里可以想想sed的工作模式,对每一行执行命令条件检测,发现匹配,就执行。 ...

2013-08-09 · 1 min · bystander

Unix sed实用教程开篇

已经看了一段时间的Linux Shell编程了,也能完成一些基本的使用,为了加深理解,恰好看到了The Unix School的一个sed&awk教程,不是简单的命令参数堆积,而是一个相当实用的系列,因此,希望能在几天内完成翻译.翻译过程不会逐字翻译,会穿插一些注释,包括自己的一些理解和其他的一些引用,作为开篇,简单说一下sed的工作机制,对后面的理解会有很大帮助。 sed是什么: sed是一个非交互式的流编辑器(stream editor)。所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出;而所谓流编辑器,是指sed每次只从文件(或输入)读入一行,然后对该行进行指定的处理,并将结果输出到屏幕(除非取消了屏幕输出又没有显式地使用打印命令),接着读入下一行。整个文件像流水一样被逐行处理然后逐行输出。(via Walk in Mindfields ) sed工作机制: sed维护两个缓冲区,pattern space和hold space,命令开始执行之前都为空。 pattern space缓冲区用于临时保存每次读取的一行的内容,大部分的匹配和替换等等操作都是针对pattern space中的内容进行的,因此不会对输入文件有任何影响,而hold space则作为后备缓冲区使用,除非指定了一些特殊的命令(例如D删除命令),否则pattern space中的内容会在处理完一行之后清空,但hold space中的内容在处理完每一行时不会被删除。 也就是说pattern space相当于我们的内存,hold space相当于硬盘.处理的时候在内存里,处理过的就放回硬盘.(这是我的理解,有一点点不恰当,但是因此一些概念会比较好理解.) 具体来说,可以大致分为以下几步: 1.首先,从标准输入流读取一行,移除换行符,然后存入pattern space中 2.执行指定的命令,(每个命令都有一个可选的地址(可以是行号,也可能是一个正则表达式匹配),这个地址作为一个执行命令前的测试,指定了需要对那些行进行操作。当前行只有匹配的情况下才会执行命令。) 3.当指定所有的命令都执行完了之后,pattern space内容就被处理过了,sed默认会将pattern space中的内容打印到标准输出中,移除的换行符也会打印出来。本行操作完成。 4.然后sed会读取下一行的内容,再次执行相同的操作。直到行尾。 基本上最基础的理论就差不多了.主要是这个工作机制比较重要.后面从示例中慢慢加深理解.

2013-08-09 · 1 min · bystander

《软件测试》一点笔记

这两天在读《软件测试》,书不厚,也就300页,有些观念还是挺诧异的,比如软件功能超出产品说明书也算作软件缺陷…想想也能明白,只是猛然看到还是很惊异..简单记录一下读书过程中一些重要的笔记.留作备份. 软件缺陷: 1.软件为达到产品说明书表明的功能 2.软件出现了产品说明书指明不会出现的错误. 3.软件功能超出产品说明书指明范围 4.软件未达到产品说明书虽未指出但应达到的目标 5.软件测试员认为软件难以理解,不易使用,运行速度缓慢,或者最终用户认为不好. 为什么会出现软件缺陷 最大的原因是产品说明书.而并非编程错误,第二大来源是设计方案 软件测试员的目标是发现软件缺陷,进可能早一些,确保其得到修复 完全测试程序是不可能的 不要总是报告坏消息,如果软件没有错误,就夸他们,和他们聊天 可靠性只是质量的一个方面,可能还包括功能齐全,技术制裁,包括色彩等 在设计和执行测试案例时,首先进行通过测试,在破坏性试验之前看看软件基本功能是否实现是很重要的,否则在正常使用软件时就会奇怪为什么有这么多软件缺陷 软件测试员必须测试程序的状态及其转换 动态白盒测试的目标是寻找软件缺陷,调试则是为了修复他们 静态黑盒子(审查设计说明书),动态黑盒子,静态白盒子,动态白盒子 进行白盒测试前,一定要根据说明书建立黑盒测试案例 语句覆盖是程序的所有语句执行,分支覆盖则是所有分支都被执行,条件覆盖则要保证IF语句的每一种可能性都被覆盖 优秀UI的七个要素: 1.符合标准和规范,2.灵活性,3.正确性。4.直观性。5.舒适性,6.实用性。7.一致性 测试存根用于自顶向下的测试,清查到低级模块或者把自己替换为低级模块,主要测试高级模块,外表和行为就像是低级模块

2013-07-26 · 1 min · bystander

使用CSS3的自定义字体美化文字

之前看到一些设计师的主题的字体很美,下载下来发现使用了css3的自定义字体,可以用来显示服务器上的字体,非常方便,学习了一下 1.首先得到字体 这个方法很多,本机的字体,一些国外的免费网站,比如这个:http://www.dafont.com,下载后的字体一般为ttf格式,ttf字体被很多浏览器支持,但是,IE不支持,为了兼容性,需要为IE单独设置字体文件,格式必须为eot,所以我们需要转换字体,使用在线工具,比如http://www.kirsle.net/wizards/ttf2eot.cgi,当然类似的网站有很多,根据个人爱好,随意。 2.添加内容 这里,我写一个简单的html文件,内容为 <body> <p class="test">bystander</p> </body> 在没有设置customFont这个类的css之前,字体就是默认的字体了。 3.设置css样式 @font-face { font-family:myFont;/*主流浏览器可用*/ src:url("PONCTUATION.ttf"); } @font-face { font-family:myFont;/*兼容IE*/ src:url("PONCTUATION.eot"); } .test { font-family:myFont; font-size:40px; } 显示效果就是这样的了…只是用来演示的一个字体。 因为浏览器是要自动下载这个字体文件的,所以对于英文字体没啥问题,英文字体一般这个字体文件在100k左右,和一张图片比起来,基本算不是问题,但是对于中文字体,包一般在10M-20M左右,这样是不现实的,我的想法是,可以自己制作字体包,这样只需要满足常用的一些汉字就行了,大大减少包的大小,然后去找了一下,发现了http://www.high-logic.com/font-editor/fontcreator.html这个软件,是可以直接编辑字体包的,也可以创建字体包,有空了用来试试.

2013-07-17 · 1 min · bystander

等物体填充问题

那天在群里,rich大牛提了一个问题,一个直径为10cm的球内最多能够填充直径为1cm的球多少个. 之前看到过一个类似的简单说明,就像是在一个盒子里装乒乓球,如果装满了,想继续装,如何办?经验告诉我们,摇一摇盒子。。这个问题看上去简单,其实是个NP难问题…于是,查找了一些资料,比较有意思,分享一下。 首先是stetson大学efriedma教授的网页,收集了各类填充(英文是packing)问题的图示,欢迎移步:packing center ,不过这里面恰好没有球体填充(SpherePacking)的问题,然后继续查找,进入了一个可以演示球体填充问题的页面:sphere packing demo 感谢网站作者Hugo Pfoertner,这里作者解出了1-72个球的问题,但是,作者说对于n>10的情况无法证明最优化.不过这个页面的演示太帅了,推荐看看。 可以鼠标拖动旋转3D视角。 然后在数学世界看到了一球体填充问题的证明结果,见:SpherePacking,当然,下面一大堆引用我都没看..看文章里的意思是说这个填充问题填充率已经被证明最大是77.9%,但是这个上限可能还能提高,因为貌似根据这个情况,rich大牛提出的这个问题应该数量在779左右..

2013-06-29 · 1 min · bystander

委托和事件示例

C#中委托和事件的例子比较多,讲得好的非常好,就不瞎凑热闹了,推荐博客园大牛的一篇: C# 中的委托和事件 ,如果你已经有了相应的基础,但没写过相关的例子,那我这里提供一个,首先看一下规范 .Net Framework的编码规范: 委托类型的名称都应该以EventHandler结束。 委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。 然后描述一下流程: 老板监视时间变动(ComputerOffWorkTime方法),当工作时间满50后,通知员工时间到(OnNotifyOffWork方法,并传递OffWorkEventArgs参数),可以下班了,(OnNotifyOffWork方法内部调用事件NotifyOffWork),正式员工收到通知后,则下班,其他员工则清扫一下办公室 然后给出例子: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; namespace DelegateAndEvent { public class Boss { //表示工作时间 private int virTime; //下班时老板说的话 public String SaidWords { get { return "Boss:时间到,下班了"; } } //委托定义 public delegate void NotifyOffWorkEventHandler(Object sender, OffWorkEventArgs e); //事件 public event NotifyOffWorkEventHandler NotifyOffWork; //事件参数 public class OffWorkEventArgs:EventArgs { public readonly int virTime; public OffWorkEventArgs(int virTime) { this.virTime = virTime; } } //触发事件 protected void OnNotifyOffWork(OffWorkEventArgs e) { if (NotifyOffWork!=null) { NotifyOffWork(this, e); } } //执行操作 public void ComputerOffWorkTime() { for (int i = 1; i <= 50; i++) { virTime = i; if (i>=50) { OffWorkEventArgs e = new OffWorkEventArgs(i); OnNotifyOffWork(e); } } } } //正式员工 public class FormalEmployee { public static void GoHome(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss) sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("FormalEmployee:准备回家"); } } //其他员工 public class OtherEmployee { public static void CleanOffice(Object sender, Boss.OffWorkEventArgs e) { Boss boss = (Boss)sender; Console.WriteLine(boss.SaidWords); Console.WriteLine(e.virTime); Console.WriteLine("OtherEmployee:准备清扫办公室"); } } public class Program { static void Main(string[] args) { Boss boss=new Boss(); //注册事件 boss.NotifyOffWork += FormalEmployee.GoHome; boss.NotifyOffWork += OtherEmployee.CleanOffice; //老板开始计时 boss.ComputerOffWorkTime(); } } }

2013-06-25 · 1 min · bystander

DMP版本修改工具(C#)

最近在使用oracle导入一个dmp文件的时候,由于不知道dmp文件是如何导出的,是使用exp还是expdp导出的,所以纠结了比较长的时间,最后想到是否可以查看dmp文件的一些辅助信息呢,于是有了这个工具。 在使用dmp导入的时候报如下错误 IMP-00010: 不是有效的导出文件,标题验证失败 IMP-00000: 未成功终止导入 据说有两个可能,1个是文件本身损坏,另一个是版本问题,多出现在高版本导出的数据向低版本导入。解决方法就是修改一下dmp文件就行了。dmp文件头部大概9个字节处标识了版本号用来头部验证。对于非常大的dmp我们不能直接用文本编辑器打开,因此找找资料,写个工具。本机一个12GB的文件已测试。 工具使用很简单,选择文件,识别出来版本,按格式改成导入端oracle的版本值,然后即可正常导入11G-10G测试成功。 下载地址:DMP版本修改工具

2013-06-11 · 1 min · bystander

阿里巴巴5月5日综合算法题详解

之前参加了阿里的笔试和电面,让后天那个敏感的日子去参加现场面,就去看了一下那天笔试的最后一道综合题,看着网上清一色最后一道题不知道从哪转的答案,不忍直视,一看代码就是错的,最直接的就是求中位数连奇偶性都不判断,直接处以2..这,另外当在无法整除的情况下,数据结果错误。 这道题的大意是:有一个淘宝商户,在某城市有n个仓库,每个仓库的储货量不同,现在要通过货物运输,将每次仓库的储货量变成一致的,n个仓库之间的运输线路围城一个圈,即1->2->3->4->…->n->1->…,货物只能通过连接的仓库运输,设计最小的运送成本(运货量*路程)达到淘宝商户的要求,并写出代码。 解题思路: 假设n个仓库的初始储货量分别为warehouse[1],warehouse[2],…,warehouse[n] 计算平均储货量 average = (warehouse[1]+warehouse[2]+...+warehouse[n])/n 就算出来了最终的结果中,每个仓库应该有的存量 首先,从仓库1向仓库n运送k; 然后,从1到n-1,依次向下运送某一特定值,使得每一个仓库的余量都为average,剩下的问题就是求总代价的最小值了。 设第0步从1仓库向n仓库(注意因为是圆圈,所以路径长度是1)运出k存量,k可以为负,如果为负数,意味着从n向1运输|k|存量,然后从循环,从(1到n-1),从i仓库向i+1仓库运输,运输的量需要保证i仓库在运输完毕后等于average 第0步(从仓库1向仓库n运送k):花费代价为 |k|, 第1步(确保仓库1的余量为average):需要花费代价为 |warehouse[1]-average-k| 也就是从1向2伙从2向1运输 3. 第2步(确保仓库2的余量为average):代价为 |warehouse[2]+warehouse[1]-average-k-average|=|warehouse[1]+warehouse[2]-2*average-k| … n-1.第n-1步:代价为 |warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k| 此时,仓库n剩下的货物量: (warehouse[n]+k)+warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k=(warehouse[1]+warehouse[2]+...+warehouse[n])-(n-1)*average=average 刚好也满足,其实这里不用推导,因为平均值是算好的,所以最胡一定是刚好完成的。 总的代价为: |k|+|warehouse[1]-average-k|+|warehouse[1]+a[2]-2*average-k|+...+|warehouse[1]+warehouse[2]+...+warehouse[n-1]-(n-1)*average-k| 不妨令sum[i] = warehouse[1]+warehouse[2]+…+warehouse[i]-i*average 则,总代价可表示为:|k|+|sum[1]-k|+|sum[2]-k|+…+|sum[n-1]-k| 这个式子可以看成在水平数轴上寻找一个点k,使得点k到点0,sum[1],sum[2],sum[3],…,sum[n-1]的距离之和最小,显然k应该取这n个数的中位数。至此问题解决。 给出详细注释代码: #include "stdafx.h" #include <iostream> #include <algorithm> #include<string> using namespace std; const int X = 100000; double sum[X],warehouse[X]; int n; double Abs(double x) { return max(x,-x); } int _tmain(int argc, _TCHAR* argv[]) { while(true) { double total = 0; double mid=0; cout<<"请输入仓库数目:"; cin>>n; //读入n个仓库的值,并计算总数 for(int i=1;i<=n;i++) { cout<<"请输入第"<<i<<"个仓库的存量:"; cin>>warehouse[i]; total += warehouse[i]; } //计算每个仓库应该最终存储的值 double average = total/n; //计算sum数组 for(int i=1;i<n;i++) sum[i] = warehouse[i]+sum[i-1]-average; //排序后打算去中位数 //sort采用半开半闭区间,所以排序为0~n-1 sort(sum,sum+n); //这个可以自己举个数字就知道了 if(n%2!=0) { mid = sum[n/2]; } else { mid=(sum[n/2]+sum[n/2-1])/2; } cout<<"应该从1开始,运输"<<mid<<"货物,然后依次保证符合条件即可"<<endl; double ans = Abs(mid); for(int i=1;i<n;i++) ans += Abs(sum[i]-mid); cout<<"总成本花费是:"<<ans<<endl; cout<<"----------------------------------------------------------------------"<<endl; } return 0; } 思路借鉴了:http://hi.baidu.com/hujunjiehit/item/54204f01931ee6c49157184c 错误之处欢迎留言指出..

2013-06-02 · 1 min · bystander

邻接表实现无向图(C++)

很早以前写的代码了,贴出来做个备份吧。用向量来存储一条邻接链表,存储可连通值。实现了判断是否连通,添加边,添加顶点的功能。 UnDirectGraph.h #pragma once #include "stdafx.h" #include <vector> using namespace std; class UnDirectGraph { private: int vCount; vector<int> *adj; public: int GetVCount(); UnDirectGraph(int vCount); void AddEdge(int v,int w); vector<int> &Vadj(int v); bool IsConnected(int v,int w); }; UnDirectGraph.cpp #pragma once #include "stdafx.h" #include "UnDirectGraph.h" using namespace std; UnDirectGraph::UnDirectGraph(int _vCount) { this->vCount=_vCount; adj=new vector<int>[vCount]; for (int i=0;i<vCount;i++) { adj[i].clear(); } } void UnDirectGraph::AddEdge(int v,int w) { adj[v].push_back(w); adj[w].push_back(v); } vector<int>& UnDirectGraph::Vadj(int v) { return adj[v]; } bool UnDirectGraph::IsConnected(int v,int w) { for (vector<int>::iterator iter=adj[v].begin();iter!=adj[v].end();iter++) { if (*iter==w) { return true; } } return false; } int UnDirectGraph::GetVCount() { return vCount; } 代码还算清晰,就不解释了,有问题留言反馈。谢谢。

2013-05-31 · 1 min · bystander