前奏
今天又来了一个比之前更有意思的一个需求。
需要提取两项数据,1. 包含两层目录下面的不带后缀的文件名;2. 这些文件的修改时间。
然后将这两个关联的数据插入一个表中,供后续和其他表关联查询使用。
1 | find . -name "*.zip" -print | xargs ls --full-time | head -n 3 |
如,把这三行的 2019-02-18 02ef1fefebcef1fddf 摘出来。
然后创建数据库:
1 | CREATE TABLE 'tmp_code' ( |
最后塞进去数据库。
思路
我的第一反应是: 先使用命令把1
2
32019-02-18 02ef1fefebcef1fddf
2019-03-19 305c3eae0cac4fcfd0
2019-05-11 0640aa46bf544aacfx
拿出来,然后使用我擅长的 vim 文本编辑器批量编辑。
确实也是可以实现。只需要使用 Ctrl + v 批量, 配合制作一两个宏。
vim 宏拼接sql 技巧
比如录制宏部分可以使用, 比如单独插入一个字段
分别转化成单条插入sql(思路一)
第一行单独处理, 然后我们从第二行开始制作宏1
2
3
4
5
6
7
8qij
IINSERT INTO tmp_tb (code) values ('
Ctrl+[
A');
Ctrl+[
q
-- 查看总行数n, 移动光标在第一行时,普通模式下执行(n-2)次回放宏:如 n = 100, 则执行时是 98@i
n-2@i
或者vim批量编辑拼接成 insert sql (思路2)
录制宏:
1 | q |
查看总行数n, 移动光标在第一行时,普通模式下执行(n-1)次回放宏:如 n = 100, 则执行时是 99@i
1 | n-1@i |
首行 输入
1 | insert into tmp_tb code values ( |
然后把结尾的 ); 放到最后一行
得高人指点 awk 和 sed 精要
这里转而使用 awk 和 sed 实现一行搞定, 具体可以这样:
1 | find . -name "*.zip" -print | xargs ls --full-time | awk '{print $6,$9}' | sed -r 's#.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/(\S+)\.zip$#INSERT\ INTO\ tmp_tb\ \(ctime,code\)\ values\ (\1 \2)#' >> tmp_code.sql |
- 逐一备注解释一下:
1 | find . -name "*.zip" -print |
是为了 找到当前目录及子目录中所有的 .zip 结尾的文件。
- “|” 是管道命令。
- 紧接着将文件的更改时间打印出来 xargs ls –full-time 。
- 然后,使用 awk awk中介绍过 的 awk 命令,默认空格作为分割符,将文本分离出来, $6, $9分别是空格分割的这么多列里,第六,第九列分别就是时间和文件信息的字符串。此时,时间已经拿到年月日,但是第九列却是带路径带后缀 ./5/0/02ef1fefebcef1fddf.zip 这样的字符串。
- 然后就到 sed 粉墨登场:
1 | sed -r 's#.*([0-9]{4}-[0-9]{2}-[0-9]{2}).*/(\S+)\.zip$#INSERT\ INTO\ tmp_tb\ \(ctime,code\)\ values\ (\1 \2)#' |
sed 有一个绝妙的地方,就是可以使用像 (匹配模式) 这样的模式,匹配起来, 然后 使用 \1 , \2 这样拿到前面的匹配模式里原文的匹配的字符串,可以理解为一个变量。 单条 sed 一共可使用 9 个这样的匹配模式。
于是就可以完成这个需求了。 对于成千上万,特别是超过 vim 能承受的打开速度和编辑的文件来说,awk 和 sed 配合 其他比如 find, grep, xargs 等命令,简直是犹如神助!
- 最后用
1
>> tmp_code.sql
把终端的标准输出都导入一个 tmp_code.sql 文件里面去。
- 数据库
1
source tmp_code.sql
入库。收工。
人呀,只要你给机会,他什么事情都能干得出来。