在过去的几天里,我一直想写点东西,介绍一下我最近使用命令行和正则表达式进行文本挖掘的一些小经验。当然,网上已经有很多图像化工具和在线库可以使我们以更少的代码进行文本处理。例如,Python 内置的正则表达式模块 "re" 就具有丰富的特性可以帮助我们进行文本处理。 另一方面呢,"BeautifulSoup" 在网页扫描和原生网页处理方面具有很好的特性。当我犯懒不想写代码的时候,我也会使用这些工具帮助我快速处理大量文本文件。
但是,我更喜欢使用命令行,当我进行文本处理和文件管理时,使用命令行给我一种如鱼得水的感觉。这篇教程中,我将使用命令行和正则表达式来处理那些原生且繁杂的 json 文件与 HTML 文件。这篇教程也有助于我们理解文本处理机制。而我假设你(读者)已经有对正则表达式和 bash 命令有一些基本的了解。
第一部分,我会展示一下如何将 'grep', 'sed', 'tr', 'column', 'sort', 'uniq', 'awk' 这些命令与正则表达式结合起来对原始的杂乱文本进行处理,以便我们深入理解文本中所包含的内容。作为示例,我将会使用由 World Library 公司的 Gutenberg 项目提供的莎士比亚全集作为我们的实验处理文本。
我们可以从网上下载莎士比亚全集。我将下载好的文本命名为 "Shakespere.txt"。接下来呢,让我们首先查看一下文件大小:
ls -lah shakes.txt
### Display:
-rw-r--r--@ 1 sabber staff 5.6M Jun 15 09:35 shakes.txt
'ls' 是一个 bash 命令,用于显示指定目录下所有的文件与文件夹。其中 '-l' 参数表示需要显示文件类型,用户,用户组,文件大小,日期以及文件名。'-a' 表示需要显示包括隐藏文件在内的所有文件。而 '-h' 是我最喜欢用的参数之一,它表示以用户可读的方式显示文件大小。shakes.txt 文件的大小是5.6Mb。
接下来,让我们看看这个文件的具体内容。使用 'less' 和 'tail' 命令可以显示文件的部分内容。显然,从命令名上我们就可以看出它们的作用。'less' 命令用于一页一页的查看文本文件的内容,它和 'more' 命令很相似,但却比 'more' 更加强大,因为它可以在查看文件时上下翻动(而 'more' 只可以向下翻动)。 '-N' 用于指定每页的查看的行数。与 'less' 相似, 'tail' 命令用于查看文件最后几行的内容。
less -N shakes.txt
### Display:
1
2 Project Gutenberg’s The Complete Works of William Shakespeare, by William
3 Shakespeare
4
5 This eBook is for the use of anyone anywhere in the United States and
6 most other parts of the world at no cost and with almost no restrictions
7 whatsoever. You may copy it, give it away or re-use it under the terms
从结果可以看出,前几行与莎士比亚作品无关,而是介绍了 Gutenberg 这个项目。同样,后面几行的内容也与莎士比亚无关。所以,我会使用 'sed' 命令,删除首尾无关的内容,具体命令如下:
cat shakes.txt | sed -e '149260,149689d' | sed -e '1,141d' > shakes_new.txt
上面的这行代码,可以删除文件尾部从 149260 到 149689 行,以及开始部分前 141 行的内容。删除的内容是一些关于版权、Gutenberg 项目以及作品内容介绍的无关内容。现在,让我们使用管道(pipe)和 'awk' 对文件内容做一些统计分析。
cat shakes_new.txt | wc | awk ''
### Display
Lines: 149118 Words: 956209 Character: 5827807
在上面的代码中,我们首先使用 'cat' 命令提取整个文本内容,然后使用管道接上 'wc' 命令去计算文件中有多少行,多少字以及有多少字符。最后,使用 'awk' 将这些信息打印出来。当然,还有很多其他的方法可以实现计数与打印的功能,你也可以使用其他可用的方法。
现在,是时候对文本进行清理以及其他处理,以便进行接下来的深入分析。清理工作包括了:将文本内容全部转换为小写;删除数字;删除标点符号;删除高频单词(例如停止词,a, the, or 等等)。清理工作不限于这些步骤,需根据实际情况而定。在此我只展示了一些必要的步骤,所以只关注我们上面提到的处理步骤。 首先,将所有的大写字母或者单词转换为小写,然后删除数字和标点符号。为了实现这一操作,我使用的是 'tr' 命令,它可以从文本中对字符进行转换或者删除。
cat shakes_new.txt | tr 'A-Z' 'a-z' | tr -d [:punct:] | tr -d [:digit:] > shakes_new_cleaned.txt
上面的命令,会首先将整个文档转换为小写然后删除所有的标点符号和数字。
### Display before:
1 From fairest creatures we desire increase,
2 That thereby beauty’s rose might never die,
3 But as the riper should by time decease,
4 His tender heir might bear his memory:
5 But thou contracted to thine own bright eyes,
6 Feed’st thy light’s flame with self-substantial fuel,
7 Making a famine where abundance lies,
8 Thy self thy foe, to thy sweet self too cruel:
9 Thou that art now the world’s fresh ornament,
10 And only herald to the gaudy spring,
11 Within thine own bud buriest thy content,
12 And, tender churl, mak’st waste in niggarding:
13 Pity the world, or else this glutton be,
14 To eat the world’s due, by the grave and thee.
### Display after:
1 from fairest creatures we desire increase
2 that thereby beautys rose might never die
3 but as the riper should by time decease
4 his tender heir might bear his memory
5 but thou contracted to thine own bright eyes
6 feedst thy lights flame with selfsubstantial fuel
7 making a famine where abundance lies
8 thy self thy foe to thy sweet self too cruel
9 thou that art now the worlds fresh ornament
10 and only herald to the gaudy spring
11 within thine own bud buriest thy content
12 and tender churl makst waste in niggarding
13 pity the world or else this glutton be
14 to eat the worlds due by the grave and thee
“切分”(tokenization)是自然语言处理中的一个基本预处理操作。而切分可以分别基于单词或者句子进行。在本文中,我会演示一下,如何对文件进行切分操作。在 bash 命令中,我们可以使用 'sed', 'awk' 和 'tr' 之类的命令执行切分处理。我认为 'tr' 命令比较简单易懂。在下面的代码中,首先提取我们之前以及处理过的文件内容,然后使用 'tr' 以及 's' 和 'c' 两个参数将每个单词都变为单独的一行。关于 'tr' 命令的详细用法以及其各种各样的功能可以参考 StackExchange 网站的相关回答。
cat shakes_new_cleaned.txt | tr -sc ‘a-z’ ‘\12’ > shakes_tokenized.txt
### Display (First 10 words)
1 from
2 fairest
3 creatures
4 we
5 desire
6 increase
7 that
8 thereby
9 beautys
10 rose
现在我们已经将所有的单词进行了切分,然后我们就可以进行一些分析,来获取其他的信息,例如,整个莎士比亚作品中,哪个单词出现的频率最高,哪个单词的频率最低。为了实现这一目标,在下面的代码中,我首先使用了 'sort' 命令来对所有的单词进行排序,然后使用带有 '-c' 参数的 'uniq' 命令,计算出每个单词出现的频率。'uniq -c' 与 Pandas 或者 SQL 中的 'groupby' 类似。最后呢,将所有的单词以其出现的频率进行升序(频率最小的排前)或者降序(频率最大的排前)排序。
cat shakes_tokenized.txt | sort | uniq -c | sort -nr > shakes_sorted_desc.txt
### Display
29768 the 28276 and 21868 i 20805 to 18650 of 15933 a
14363 you 13191 my 11966 in 11760 that
cat shakes_tokenized.txt | sort | uniq -c | sort -n > shakes_sorted_asc.txt
### Display
1 aarons 1 abandoner 1 abatements 1 abatfowling
1 abbominable 1 abaissiez 1 abashd 1 abates
1 abbeys 1 abbots
上面的结果,为我们揭示了一些有趣的发现。例如,出现频率最高的前十个单词不是代词,就是介词,或着是连词。如果你想从文本中找到更多抽象信息的话,我们就需要将所有的停止词都删掉——即所有的介词,代词,连词以及助动词。当然,是否删除主要取决于你的目的。有时候,你可能只对介词比较感兴趣,在这种情况下,你就可以保留所有的介词。从结果中可得到,出现频率最小的单词是 abandoner(孤儿), abatements(销减),abashd 。 语言学或文学专业的学生可以通过对莎翁作品的文本分析,更好地感知其作品的特点。
接下来呢,我演示一下在命令行中使用 'awk' 命令删除所有的停止词。在本文中,我们使用的是NLTK 的英语停止单词表。另外,我自己也在其中添加了一些单词。关于下面这行代码的具体含义可以参考StackOverflow 中的相关问题。关于 'awk' 命令的具体参数使用可以参考 'awk'命令手册(在命令行中输入 'man awk')。
awk ‘FNR==NR(!($2 in w))’ stop_words.txt shakes_tokenized.txt > shakes_stopwords_removed.txt
在删除了所有的停止词后,让我们将所有的单词按照之前的方法进行升序和降序排列。
cat shakes_stopwords_removed.txt | sort | uniq -c | sort -nr > shakes_sorted_desc.txt
### Display most frequent
3159 lord 2959 good 2924 king 2900 sir
2634 come 2612 well 2479 would 2266 love
2231 let 2188 enter
cat shakes_stopwords_removed.txt | sort | uniq -c | sort -n > shakes_sorted_asc.txt
### Display least frquent
1 aarons 1 abandoner 1 abatements 1 abatfowling
1 abbominable 1 abaissiez 1 abashd 1 abates
1 abbeys 1 abbots
我们可以看到,在删除了停止词后,在莎士比亚文集中出现频率最高的单词是 'Lord',然后是 'good'。单词 'love' 也名列前茅。而出现频率最低的单词没有任何变化。
翻译:奔跑的笤帚把子
审校:名扬
编辑:Queen
原文:
https://www.kdnuggets.com/2018/07/text-mining-command-line.html
关注集智AI学园公众号
获取更多更有趣的AI教程吧!
搜索微信公众号:swarmAI
学园网站:campus.swarma.org
商务合作和投稿转载|swarma@swarma.org
领取专属 10元无门槛券
私享最新 技术干货