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. iOS 之 支付

    现在广泛应用的是微信支付和支付宝支付,这两种应该覆盖了几乎所有网上消费的用户,所以我们就用这两种支付方式就够了.2014年用过支付宝的网民购物占比有94%. 1. iOS 之 微信支付 2. iOS ...

  2. 安卓自定义类似TabHost的导航栏

    有时候为了项目需要我们要自定义一些导航控件,类似下面这样. 下面给大家讲讲我是怎么实现的, 1.素材准备(这个都是美工的事情) 2.①资源文件共有五个 如下: activity_main_first. ...

  3. Angular - - ngList、ngRepeat、ngModelOptions

    ngList 在文本输入的分隔的字符串和字符串数组间做转换,可以是一个固定的字符串分隔符(默认逗号)或正则表达式. 格式:ng-list=”value” value:表达式  通过这个值分隔字符串. ...

  4. php session 生命周期代码实例

     php session 生命周期代码实例        我们为什么需要Session,就是因为我们需要存储各个用户的状态数据.那么试问,如果由你来设计解决这个需求的方案,那么也许你会设置这样一个数据 ...

  5. Heka 编译安装后 运行报错 panic: runtime error: cgo argument has Go pointer to Go pointer

    Heka 编译安装后 运行报错 panic: runtime error: cgo argument has Go pointer to Go pointer 解决办法: 1.  Start heka ...

  6. Maven与Antx(整理)

    http://blog.csdn.net/ghost_t/article/details/5709640 一.Maven与Antx概况: Antx简介   在讲为什么使用maven之前我想说一下,an ...

  7. oracle取字符串长度的函数length()和hengthb()

    http://blog.itpub.net/161195/viewspace-613263/ lengthb(string)计算string所占的字节长度 :返回字符串的长度,单位是字节 length ...

  8. 个人对现在大众对perl的偏见的一些见解

    最近我都在一些论坛和交流社区学习,发现很多人对perl有很大的偏见. 以我学习那么久的Perl来说吧,也算是有一些小经验了,所以我总结了大家对perl的偏见的原因,无非就是是下面两个的两个原因: 1. ...

  9. PHP使用hash_algos函数计算哈希值,之间的性能排序

    PHP从5.1.2版本以上开始支持hash_algos函数,看这个名字就知道了,algos在英文中也表示算法的意思,hash_algos就是哈希算法,收集了一些常用的哈希算法,从5.1.2开始不同版本 ...

  10. 《连载 | 物联网框架ServerSuperIO教程》- 15.数据持久化接口的使用。附:3.2发布与版本更新说明。

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...