这是MIT Missing Semester系列的第四讲。关于vim的第三讲跳过。Data Wrangling在这里的意思是对数据做变换(Transformation)。例如将一个MP4格式的视频转换为AVI,或或者是从日志中提取所需要的结构化文本信息。具体到本课,主要是处理文本信息:如何匹配到我们感兴趣的信息,如果构建一个处理的pipeline等。
`
正则表达式
在很久以前,总结了一篇关于python中的正则表达式的常用用法,竟然也是博客的第一篇文章:python正则表达式。
推荐一个交互式的正则表达式学习网站。这里有一些简单的规则:
.
匹配任意字符,除了\n
*
匹配前缀的任意个,包括0个+
匹配前缀的任意个,不包括0个?
匹配前缀的0个或1个[abc]
匹配给定集合里面的元素,例如这里匹配a
或b
或c
(ab)
匹配给定的组合,例如这里匹配ab
(exp1|exp2)
匹配exp1
或exp2
^
指示一行的开头$
指示一行的结尾
要注意的是,(
在下面的sed中如果没有特殊说明,被视为普通字符,需要加上-E
选项。
如果我们想要指定具体的次数呢?可以使用.{n}
的形式。例如,a{3}
表明匹配3个a
;[ab]{4}
匹配4个a
或b
。使用range表达式,表明在某个范围内:.{2,5}
表示2到5个任意字符。
sed
sed(Stream Editor)可以帮助我们变换文本。sed每次从输入流中读入一行,作相应变换,并输出。
A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline)
这里是一个sed的教程,下面结合该教程和讲师的实例,对sed使用做一说明。
sed的其他用法
这里首先对sed的其他用法做一说明。
使用-e
可以传入一些命令,例如1d
就是删除第一行。通过串联,可以删除多行。
1 | # 删除第一行和第五行 |
还可以使用-f
指示从某个文件内读取命令,
1 | echo "1d\n2d" > arg.txt |
sed对文本进行查找替换
sed最常用的场景之一,使用如下命令,将文本文件中的pattern
(一个正则表达式)替换为new
。当new
为空时,将直接删去pattern
。最后的g
如果不加,则只匹配一次,加上g
表示全局。
1 | sed 's/pattern/new/ filename/g' |
例如:
1 | # .* 表示任意多个任意字符,包括0个。所以下面会把 says hello以及它前面的内容都删掉 |
注意,.*
组合是greedy的。这意味着它会尽可能多地去匹配任意字符。
1 | echo "cat says hello to says hello to dog" | sed 's/.*says hello//' |
capture group
capture group是指我希望记住匹配到的值。在正则表达式中,使用()
括起来的就是capture group。我们可以使用\1
,\2
来引用它们。
1 | # 想知道cat对谁打招呼了 |
sort和uniq
sort,顾名思义,读入input,排序,再将它们输出。uniq,可以将紧邻的相同行进行合并。因为uniq只能合并紧邻的向同行,所以常常和sort配合使用。
1 | # -c 会在每一行前面加上一列,显示重复出现的次数 |
awk
awk是另一种stream editor。与sed相比,它更针对于成列的数据。例如,我们可以打印文本文件的第一列:
1 | awk '{print $1}' input |
awk的一般用法还会加上pattern
,例如awk 'pattern {action}' input
。例如:
1 | # $0表示非特定列,而是整行 |
awk的功能还远不止此。awk中可以使用循环,分支等语句构成更复杂的逻辑。
paste命令可以用来合并多行为一行。下面的命令将输入文件的第一列顺序拼接为一行,并使用逗号分隔。
1 | awk '{print $1}' input | paste -sd, |
The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file’s newline characters with a single tab character, and writes the resulting lines to standard output.
总结
本课主要介绍了一些常用的文本处理命令,包括sed, awk, sort, uniq, paste等。下面使用tldr命令给出这些命令的常用用法供参考。
sed
1 | ➜ ~ tldr sed |
awk
1 | ➜ ~ tldr awk |
sort
1 | ➜ ~ tldr tldr |
uniq
1 | ➜ ~ tldr uniq |
paste
1 | ➜ ~ tldr paste |
Exercise
关于正则匹配的应用
- Find the number of words (in
/usr/share/dict/words
) that contain at least threea
s and don’t have a's
ending.
1 | cat /usr/share/dict/words | grep -E '(.*a){3}' | grep -Ev "\'s$" | wc -l |
sed 使用
就地修改文件,使用-i
。最好在后面指定backup文件的后缀名,否则将不会做backup。有丢失原始数据的风险。
1 | -i extension |