记使用sed的一次坑
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的一次坑的更多相关文章
- 记C函数指针的“小坑”
今天遇到一个C函数指针的小坑,索性记下来. 我在a.c 文件里面,引用b.c 文件的函数声明作为指针引用 比如在a.c生命一个函数指针 typedef void (*free)(void *val) ...
- 记C语言浮点数运算处理 "坑" 一则
看一小段C语言程序: int main() { float x = 1.3; x = x - (int)x; ); ; } 在你心目中, 变量 I 是怎样的结果? 如果你理所当然地认为是3的话, 那么 ...
- 记一个JAVA关于日期的坑
JAVA解析日期格式代码,之前一直写成:“yyyy-MM-dd hh:mm”,比如"2016-01-18 11:00"."2016-01-18 15:00"都可 ...
- 记一次搭建vsftp服务器坑
避免踩坑,特此记录... yum -y install vsftpd useradd -d /www -s /sbin/nologin sui # 修改vsftpd配置文件/etc/vsftpd/vs ...
- 记一次FTP下载踩坑的故(shi)事(gu)
下班前领导忽然要求我将客户的日志服务器上一些日志拷贝到测试服务器中,不过领导只提供给我FTP的连接方式,很明显就是要我用FTP方式去做啦 一般来说FTP批量下载也就上网随便找个脚本的事,但是却成了我疯 ...
- 记一次kubernetes驱逐踩坑
最近在公司的线上服务器上发现了一个现象: 将某个node的kubelet短暂的停掉之后,其上的pod马上会被驱逐,这让笔者大吃一惊,印象之中,停掉kubelet后,该node会变为NotReady状态 ...
- 记一个开发是遇到的坑之Oralce 字符串排序
简单描述一下情况,就是存储过程中用一个字符串类型的字段作为患者就诊的排序号,结果莫名发现叫完1号后叫了11.12等患者.用户的反馈不一定准确,自己加了日志的,赶紧拷贝日志来观察一下.结果发现实际情况就 ...
- Java小菜求职记-以前在Dubbo踩的坑,这次全被问到了,这下舒服了
前传 小林求职记(五)上来就一连串的分布式缓存提问,我有点上头.... 终于,在小林的努力下,获得了王哥公司那边的offer,但是因为薪水没有谈妥,小林又重新进入了求职的旅途,在经历了多次求职过程之后 ...
- 记一次使用openrowset 的坑
前几天被老大训斥连openrowset 都不会用,然后我就去看了文档,想测试一下栗子~ openrowset 的具体语法我就不贴了,戳这里:https://msdn.microsoft.com/zh- ...
随机推荐
- Android 控件布局常用属性
<!--单个控件经常用到android:id —— 为控件指定相应的IDandroid:text —— 指定控件当中显示的文字,需要注意的是,这里尽量使用strings.xml文件当中的字符串a ...
- Mysql和Oracle的一些语法区别
作为一个有追求的程序猿,当然要不断的学习,巴拉巴拉巴拉...好了,贴一个网址给大家,哈哈 MySQL与Oracle 差异比较:http://www.cnblogs.com/HondaHsu/p/364 ...
- 阿里云安装wordpress遇到的问题
在阿里云服务器上安装Nginx,php5.3.3环境,使用阿里云的RDS数据库 1,安装wordpress,提示您的PHP似乎没有安装运行WordPress所必需的MySQL扩展 解决方案:移除已经安 ...
- HTML5学习笔记四:html5结构
一.大纲:大纲即文档中各内容区块的结构编排 1. 显示编排内容区块:使用section等元素创建文档结构,每个内容区块使用标题(h1~h6,hgroup); 2. 隐式编排内容区块:根据页面所书写的各 ...
- 除trigger()方法外的jquery手动触发事件
trigger()可以触发指定事件是大家基本都知道的了. 除了trigger()之外我们也可以这样来触发: html <div id="box" style="he ...
- Selenium2(java)TestNG的使用 七
TestNG,即Testing Next Generation,下一代测试技术,是一套根据JUnit和NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做 ...
- Eclipse中应用的调试
作为编程人员,程序的调试是一项基本功.在不使用IDE的时候,程序的调试多数是通过日志或者输入语句(System.out.println)的方式.可以把程序运行的轨迹或者程序运行过程中的状态显示给用户, ...
- js实现360度图片旋转
▓▓▓▓▓▓ 大致介绍 这次是一个简单的效果,就是思路的问题 效果: ▓▓▓▓▓▓ 思路 旋转的效果就是根据鼠标的的移动距离来显示不同的图片,形成视觉差,仿佛就是在正真的旋转 由于效果是根据鼠标的移动 ...
- 使用Navicat Premium 链接本地数据库的方法
在工作中,为了更方便的使用数据库,不免会用到Navicat Premium: 于是在重新安装电脑系统之后,原本想在其中链接一下本地数据库, 只是在链接途中要写的密码一项却不晓得应该写什么,想了很久密码 ...
- Professional C# 6 and .NET Core 1.0 - What’s New in C# 6
本文为转载,学习研究 What's New in C# 6 With C# 6 a new C# compiler is available. It's not only that a source ...