sed做为linux下的三剑客,自然功能强大,但是如果使用不当,反而适得其反,今天就因为这个命令采了很深坑,分析一下原因,以谏后来者。

情景回顾:

项目中使用的一个python爬虫采用的是多线程并发爬取,输入为一个存放url的文件,因为程序随时可能停止,所以每次重启程序的时候需要将以爬取过的url去除,实现思路如下:

但是这样实现自动化的时候多有不便,一个程序就涉及五个文件,在加上其他的逻辑,文件众多,用shell脚本实现自动化写出来的代码可读性差,不易理解,所以想重新更改一下策略。有一种思路就是在程序启动的时候将文本读入一个list,然后删除掉处理完成的,程序关闭时将list写入文件,这样看似轻松,但是文本内容过大,而且如果程序异常退出,就会丢失掉内存中list内容,干了半天白干了。

旁边的一个小哥给了个建议,说是处理完就直接从Input中删掉,这样就不用再写shell自动化了,程序重启直接读取input文件就Ok了。

但是如何用python实现删除文件中指定的一行呐?总不能把文件读成列表,然后把那一行删除,然后再写回文件。因为是个大文件,这样效率很低。尤其是在多线程并发的情况下这样会导致大量IO,旁边的小哥又献策说可以用os.system('sed -i 1001d %s' % filename) 系统调用sed删除该行,在无可奈何的情况下,一想这样编码也不是很简单吗? 于是就欣然接收了这个提议,很快就实现了。

程序运行起来后才发现不是自己想的那样,自己还是没有搞明白sed,

原理剖析:

sed 是一种在线流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

使用-i选项可以直接在原文件进行修改,他会将sed原本输出到屏幕的内容输出到一个以sed开头的临时文件,处理完毕后他会将这个临时文件替换原本的文件,如果运行的时候出现错误,这个临时文件就不会被删除,一直留在那里。

而且在多个线程同时调用sed的时候,就会出现以下情况

线程B删除了第二行但第一行并未删除,当他处理完的时候替换原文本又会将第一行带回去,这样本来已经在线程A中删除的第一行,现在又出现了,于是被下一个线程读取处理,又被删除,又被替换回来,这样就造成一个循环,运行程序但并不能有效删除处理完毕的行。

         sed固然强大,但是应该在直到其实现原理的情况下合理调用,避免在多线程情况下调用。

记使用sed的一次坑的更多相关文章

  1. 记C函数指针的“小坑”

    今天遇到一个C函数指针的小坑,索性记下来. 我在a.c 文件里面,引用b.c 文件的函数声明作为指针引用 比如在a.c生命一个函数指针 typedef void (*free)(void *val) ...

  2. 记C语言浮点数运算处理 "坑" 一则

    看一小段C语言程序: int main() { float x = 1.3; x = x - (int)x; ); ; } 在你心目中, 变量 I 是怎样的结果? 如果你理所当然地认为是3的话, 那么 ...

  3. 记一个JAVA关于日期的坑

    JAVA解析日期格式代码,之前一直写成:“yyyy-MM-dd hh:mm”,比如"2016-01-18 11:00"."2016-01-18 15:00"都可 ...

  4. 记一次搭建vsftp服务器坑

    避免踩坑,特此记录... yum -y install vsftpd useradd -d /www -s /sbin/nologin sui # 修改vsftpd配置文件/etc/vsftpd/vs ...

  5. 记一次FTP下载踩坑的故(shi)事(gu)

    下班前领导忽然要求我将客户的日志服务器上一些日志拷贝到测试服务器中,不过领导只提供给我FTP的连接方式,很明显就是要我用FTP方式去做啦 一般来说FTP批量下载也就上网随便找个脚本的事,但是却成了我疯 ...

  6. 记一次kubernetes驱逐踩坑

    最近在公司的线上服务器上发现了一个现象: 将某个node的kubelet短暂的停掉之后,其上的pod马上会被驱逐,这让笔者大吃一惊,印象之中,停掉kubelet后,该node会变为NotReady状态 ...

  7. 记一个开发是遇到的坑之Oralce 字符串排序

    简单描述一下情况,就是存储过程中用一个字符串类型的字段作为患者就诊的排序号,结果莫名发现叫完1号后叫了11.12等患者.用户的反馈不一定准确,自己加了日志的,赶紧拷贝日志来观察一下.结果发现实际情况就 ...

  8. Java小菜求职记-以前在Dubbo踩的坑,这次全被问到了,这下舒服了

    前传 小林求职记(五)上来就一连串的分布式缓存提问,我有点上头.... 终于,在小林的努力下,获得了王哥公司那边的offer,但是因为薪水没有谈妥,小林又重新进入了求职的旅途,在经历了多次求职过程之后 ...

  9. 记一次使用openrowset 的坑

    前几天被老大训斥连openrowset 都不会用,然后我就去看了文档,想测试一下栗子~ openrowset 的具体语法我就不贴了,戳这里:https://msdn.microsoft.com/zh- ...

随机推荐

  1. Linux 下如何安装 JDK ,以 Ubuntu 为例。

    http://www.cnblogs.com/memory4young/p/ubuntu-install-jdk.html 一.下载 首先,当然是要下载了. 地址:http://www.oracle. ...

  2. excel导入到Orcle

    Excel导入到Oracle中 在Oracle中创建一个表,与excel的表头对应 将excel文件保存为.csv格式 创建一个.ctl文件 load data infile 'd:\xiaoyou. ...

  3. 使用PopupMenu创建弹出式菜单

    PopupMenu代表弹出式菜单,它会在指定组件上弹出PopupMenu,默认情况下,PopupMenu会显示在该组件的下方或上方.PopupMenu可增加多个菜单项,并可为菜单项增加子菜单. 使用P ...

  4. PHP header( ) 禁止页面后退

    header("Cache-control:no-cache,no-store,must-revalidate"); header("Pragma:no-cache&qu ...

  5. 避免Node.js中回调地狱

    为了解决这个阻塞问题,JavaScript严重依赖于回调,这是在长时间运行的进程(IO,定时器等)完成后运行的函数,因此允许代码执行经过长时间运行的任务. downloadFile('example. ...

  6. AC日记——统计难题 hdu 1251

    统计难题 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)Total Submi ...

  7. linux iptables 配置

    1.查看已有配置 iptables -L -n 2.清除原有规则. iptables -F        清除预设表filter中的所有规则链的规则 iptables -X        清除预设表f ...

  8. JAVA中获取当前运行的类名,方法名,行数

    JAVA中获取当前运行的类名,方法名,行数 public static String getTraceInfo(){ StringBuffer sb = new StringBuffer(); Sta ...

  9. 关于异常“The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine”的处理

    我们在利用SqlBlukcopy技术倒2010 或者2007格式的文件到SqlServer 数据库的时候,会发生如下错误: 原因如下: 1.在用SQL SERVER 2005访问.xlsx文件(off ...

  10. SimRank协同过滤推荐算法

    在协同过滤推荐算法总结中,我们讲到了用图模型做协同过滤的方法,包括SimRank系列算法和马尔科夫链系列算法.现在我们就对SimRank算法在推荐系统的应用做一个总结. 1. SimRank推荐算法的 ...