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. QGis(三)查询矢量图层的要素属性字段值(转载)

    QGis(三)查询矢量图层的要素属性字段值 https://github.com/gwaldron/osgearth/issues/489 当加载一个矢量图层后,如果要查看要素的属性字段值,则需要实现 ...

  2. ThinkPHP 自动验证实例

    //array(验证字段1,验证规则,错误提示,[验证条件,附加规则,验证时间]),protected $_validate = array( ); ThinkPHP 自动验证定义的附加规则如下: r ...

  3. Angularjs在线api文档

    http://docs.ngnice.com/api            文档 http://www.ngnice.com/showcase/#/home/home                  ...

  4. Chrome 控制台 如何调试javascript

    上面的文章已经大致介绍了一下console对象具体有哪些方面以及基本的应用,下面简单介绍一下如何利用好chrome控制台这个神器好好调试javascript代码(这个才是我们真正能用到实处的地方) 1 ...

  5. oc是一个全动态语言,oc的一切都是基于runtime实现的!

    oc是一个全动态语言,oc的一切都是基于runtime实现的! 从以下三方面来理解runtime吧! 1. 传统的面向过程的语言开发,例如c语言.实现c语言编译器很简单,只要按照语法规则实现一个LAL ...

  6. Windows Server 2008 R2防火墙出站规则

    出战规则指Windows Server 2008 R2系统访问外部的某台计算机通信数据流. 配置防火墙阻止Windows Server 2008 R2系统通过IE软件访问外部的网站服务器,阻止Wind ...

  7. mysql 无法启动的原因Can't start server: can't create PID file: No space left on device

    一大早来到公司,看到了一个噩梦,后台总是登录不上,登录就出错,还以为被黑客入侵了.经过1个小时的排错原因如下: 我的服务器是linux的,mysql的报错日志路径是/var/log/,经过查看日志发现 ...

  8. 如何在NodeJS项目中优雅的使用ES6

    如何在NodeJS项目中优雅的使用ES6 NodeJs最近的版本都开始支持ES6(ES2015)的新特性了,设置已经支持了async/await这样的更高级的特性.只是在使用的时候需要在node后面加 ...

  9. jq基础

    $(function() {          $(".dd").attr("class","cc").append("<h ...

  10. 在ubuntu linux 中编写一个自己的python脚本

    在ubuntu linux 中编写一个自己的简单的bash脚本. 实现功能:终端中输入简单的命令(以pmpy为例(play music python),为了区别之前说的bash脚本添加了py后缀),来 ...