jojo,python的能力是有极限的

–> jojo,python的能力是有极限的

–> 我从短暂的人生当中学到一件事……

–> 越是玩弄爬虫,就越会发现python的能力是有极限的……

–> 除非超越python。

你到底想说什么?

–> 吔我bash啦!

起因

原因其实很简单,工作上需要后台导入些数据。

吭哧吭哧把原始数据整理完,搞成csv了,点个“导入”,给我来了个报错:

  • 单次导入只支持1000条

崽啊,9102年末了,我csv里面可有近百万条数据,你跟我说一次1000?我不下班啦?

然而优秀的底层员工是不会抱怨这些事情的,行吧,我自己切表总行了吧。

尝试python切割

嘴上喊着不下班了,实际上也没有这么赶时间,就先用python瞎糊了一个:

1
2
3
4
5
6
7
8
9
10
datas = {}
for n, line in enumerate(open('test.csv', 'r', encoding='utf-8-sig')):
if datas.get(n//1000):
datas[n//1000] = datas[n//1000] + [line]
else:
datas[n//1000] = [line]

for k,v in datas.items():
with open('test-{}.csv'.format(k), 'w', encoding='utf-8-sig') as f:
f.write(''.join(v))

凑合着先用了,顺便再写了个脚本自动导入到后台,先把工作做完了。

但是回过头了,贤者时间了,就开始嫌弃python不够快了。

虽然很明显原因在于我(毕竟瞎糊凑合用),想看能不能更快一点。

于是想起了bash,想起了split和xargs。

换成bash

要切割文件的话split的确很方便:

split test.csv -l 1000 -d -a 3 test__

-d -a 3指定了按3位数递增添加后缀,这样就能产生 test__001 ~ test__999 命名的切割好的文件。

但新的问题也来了,切割完需要全部加上文件扩展名:

mv test__001 test_-001.csv

但手工操作量还是太大,这时候我们就需要xargs了:

ls | grep test__ | xargs -n1 -I file mv file file.csv

ls | grep test__筛选了所有缺少扩展名的文件,管道命令传给xargs后,-n1代表一次接受一个参数,-I file告诉xargs后续命令中的file全部用参数值替换。

比如只有一个文件的时候,ls | grep test__只有一个结果test__001,xargs接收到参数,将file替换成test__001,实际执行内容就是:

mv test__001 test__001.csv

将他们组合一下:

split -l 1000 test.csv -d -a 3 test__ && ls | grep test__ | xargs -n1 -I file mv file file.csv

回车执行,1秒都不需要,爽死了。

人类是懒惰的动物

但这样还是需要自己手打需要切割的文件名,不够爽。尝试把代码再变长一点:

ls | grep .csv$ | sed ‘s/.csv//‘ | xargs -n1 -I file split -l 1000 file.csv -d -a 3 file__ && ls | grep __ | xargs -n1 -I file mv file file.csv

以管道命令分割解释一下:

  1. ls 列出当前目录下所有文件和子目录
  2. grep .csv$ 筛选扩展名是csv的所有文件
  3. sed 's/.csv//' 去除扩展名,只留文件名
  4. xargs -n1 -I file split -l 1000 file.csv -d -a 3 file__ 切割所有的文件
  5. ls 列出当前目录下所有文件和子目录
  6. grep __ 筛选文件名包含__的文件(上一步切割好的文件)
  7. xargs -n1 -I file mv file file.csv 加上扩展名

爽又死了。

EOF

尝试在windows上(Cmder+Github自带了这部分命令)做类似的操作,发现远没有在虚拟机(Ubuntu)里执行快,垃圾微软.jpg