文本处理和操作

在您使用Linux服务器的日常工作中,您可能会发现自己需要查看,操作和更改文本数据,而无需“编辑”文件本身。在本节中,我们将看看用于处理文本数据的标准Linux发行版附带的各种工具。

读取和更改数据源:示例Linux机器将在其日常活动中生成大量数据。其中大部分对您的机器管理非常重要。我们来举个例子。如果您安装了Apache Web服务器,它会不断将数据传输到两个重要的文件,即访问和错误。访问文件记录每次访问您的网站。每当有人(或某事)访问您的网站时,Apache会在该文件中创建一个包含日期,小时和所请求文件的信息的条目。错误文件用于记录错误,如服务器配置错误或错误的CGI脚本。

你可以找到好的软件来处理你的访问文件。它会告诉你在你的网页上有多少点击。它甚至会自动查找缺少或不存在的网页(称为404)的请求。这些软件中的一些非常擅长生成有关流量的信息报告,缺少网页的警告和其他网站的统计数据,但它的目标是一般网站管理员,并以一般方式显示其数据。有时候,您可能需要或需要对文件中的数据进行一些评估 - 超越这些Web统计软件包提供的内容。

我可以grep那!

希望从文件中获得的任何信息都在您的指尖,感谢grep。尽管传言相反,grep是Vulcan forfind这个词,grep代表正则表达式解析器。现在你知道了,我相信你感觉好多了。事实上,在处理正则表达式方面越熟练,系统管理就越好。让我们来看看我们的Apache访问文件的另一个例子。

假设您有兴趣查看六月份访问您网站的次数。你会在访问文件上做一个简单的grep,像这样:

码:

grep -c 'Jun/2003' access

这会给你在六月份要求的文件数量。如果你对这个月的要求有兴趣,我们可以补充一点:

码:

grep -c `date +%b` access

可以这么说,我们所做的基本上就是指挥一下。grep会将该命令的输出作为月份的名称(日期中的%b选项会给出月份名称的缩写),并在文件中查找它。

实际上是其他命令选项的命令必须放在向后或严重的重音标记内,否则它们将不起作用。

实际上你可以用你的Apache访问文件使用grep和date命令来做一些非常酷的事情。你可能只想看看今天的点击率:

码:

grep -c `date +%d/%b` access

也许你想看看什么是在同一天,但其他几个月的命中:

码:

grep -c `date +%d/` access

也许你期待更多的信息?一些Linux发行版将安装特殊的脚本来运行cron作业来压缩Apache访问文件。即使你的旧文件被压缩了,比如每个月,你仍然可以通过grep来获取信息,而不需要解压缩它们。Grep有一个版本,可以查看它使用gzip压缩的文件。这叫做,适当的zgrep

码:

zgrep -c `date +%d/` access_062003.gz

这将在同一天的网络服务器上寻找,但在六月你gzip的访问文件。(当然,除非是31号)。

说到gzip,你实际上可以做相反的事情。您可以grep文件,并根据结果,创建一个gzip'd文件。例如,如果您想在本月创建点击文件,可以这样做:

码:

grep `date +%b/` access gzip -c > access_01-20jul.gz

只要你有一些你正在寻找的东西,grep会为你提供什么样的结果。事实是我们一直在关注Apache文件。有几十个文件可能在任何特定的时刻都感兴趣,所有的文件都可以通过“grep”来给你提供重要的信息,例如,你可能对你的收件箱中有多少信息感兴趣。可以为你提供这些信息。

码:

grep -c '^From:' /var/spool/mail/penguin

如果您对邮件的来源感兴趣,那么就放弃-c选项。你应该看到这样的东西:

码:

脱字符(^)表示grep应该查找以所需表达式开头的每一行。在这种情况下,标准电子邮件消息中的“From:”标题。

说到邮件,假设有人昨天给你发了一封电子邮件,里面有你需要联系的人的名字和他/她的电话号码。你甚至不需要打开你的电子邮件客户端来获取这些信息。您可以在收件箱中查找电话号码格式的数字。

码:

grep '[0-9]-[0-9]' inbox

电话号码通常被格式化为交换号码(555-3号码)和号码本身(6677-4号码),所以grep会在它们之间用斜杠( - )分别查找分别在3和4中的任何号码。

我们用脱字符(^)来寻找以某些字符开始的行。我们还可以查找以美元($)符号结尾的特定字符。例如,如果我们想知道我们系统上的哪些用户使用bash shell,我们可以这样做:

码:

grep bash$ /etc/passwd

在这种情况下,使用的shell是/ etc / passwd文件每行中列出的最后一件事情,所以你会看到类似这样的输出:

码:

root:x:0:0:root:/root:/bin/bashmike:x:500:500:mike:/home/mike:/bin/bashdave:x:501:501:dave:/home/dave:/bin/bashlaura:x:502:502:laura:/home/laura:/bin/bashjeff:x:503:503:jeff:/home/jeff:/bin/bash

在其他命令

中使用grep在管理任务中,grep更常见的用途之一是将其他命令传递给它。例如,你很好奇你的系统资源占用了多少。eh hem ..使用:

码:

ps uax grep $USER

或者如何寻找你在十月份创建的文件:

码:

ps -l grep Oct

再次,我们可以继续很长一段时间,但我们有其他的命令来看待。不用说,你会发现grep是你最有价值的工具之一。

感觉有点awk(病房)awk是另一种工具,这将使你寻找有意义的数据更容易。awk实际上是一种特别为文本操作而设计的编程语言,但它被广泛用作管理的现场工具。

例如,让我们回到之前用grep使用的例子。你想看看你正在使用的过程。你也可以用awk来做到这一点。

码:

ps uax awk '/mike/'

和grep完全一样。但是,ps工具以表格格式显示数据,所以awk更适合于比grep更适合从中获得我们想要的部分。我们上面使用的uax选项会显示如下的信息:

码:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 3355 0.0 0.1 1344 120 ? S Jul27 0:00 crond

所以使用awk,我们可以从每一列中获得特定的信息。例如,我们可以看到root用户正在使用什么进程以及他们使用了多少内存。这意味着告诉awk从第1,2和4列中获取关于root进程的信息:

码:

ps uax awk '/root/ '

这会给我们一些这样的信息:

码:

root 1 0.3root 2 0.0root 3 0.0root 4 0.0root 9 0.0root 5 0.0root 6 0.0root 7 0.0root 8 0.0root 10 0.0root 11 0.0root 3466 0.0root 3467 0.0root 3468 0.0root 3469 0.0root 3512 0.0root 3513 7.9root 14066 0.0

你会注意到PID3513显示了更多的内存使用情况,所以你可以进一步使用awk来看看那里发生了什么。我们将添加第11列,向我们展示使用该内存的程序。

码:

ps uax awk '/3513/

而且你会看到X-window是有问题的程序:

码:

root 3513 7.6 /usr/X11R6/bin/X

我们甚至可以更进一步。我们可以使用grep来获取我们的进程正在使用的内存的总数:

码:

ps uax awk '/^mike/ { x += $4 } END { print "total memory: " x }'

awk很好,足以容纳总数:

码:

total memory: 46.8

我正在使用机器内存的将近一半。很高兴看到awk可以做数学呢!

因为它可以做数学,你也可以用它来检查某些文件的总字节数。例如,照片集中的jpgs占用的总字节数:

码:

ls -l awk '/jpg/ { x += $5 } END { print "total bytes: " x }'

ls -l的第5列显示了文件的字节,我们只是把awk加起来。

Tengo'sed'!

sed虽然是一个很好的工具,但是它在很大程度上已经被Perl中的特性所取代,它在某种程度上重复了它。我在某种程度上说,因为sed和pipe的结合使用可以让文件中的文本替换更舒适(至少对于这个作者来说)。

西班牙人是口渴的西班牙人的话,虽然你可能渴望(或者饥饿,或者其他),但是这个名字并不是从那里得来的。它代表流编辑器。正如你在我们的例子中看到的,sed基本上用于修改一个文本文件,而不必在传统的编辑器中打开它。这为系统管理员节省了不可思议的时间。

sed最常见的用途之一是改变或消除文件中的文本。假设您想查看最后一次登录您的网络的人员。你会运行一个名为lastlog的工具。这将显示每个用户最后一次登录。事实是,我们只对真正的人类用户感兴趣,而不是真正的守护进程或进程的用户,或者从字面上看是“没有人”。如果你只是运行lastlog,你会得到一堆这样的条目:

码:

mail **Never logged in**news **Never logged in**uucp **Never logged in**

当然,你可以通过把sed带入画面来使这个输出更加有意义和简洁。只需管道lastlog的输出,并让sed消除所有包含单词Never的条目。

码:

lastlog sed '/Never/d' > last_logins

在这个例子中,sed将删除(因此'd'选项)每一行包含这个单词,并发送输出到一个名为last_logins的文件。这将只包含真实的用户,你可以看到:

码:

Username Port From Latestfred pts/3 s57a.acme.com Mon Jul 14 08:45:49 +0200 2011sarah pts/2 s52b.acme.com Mon Jul 14 08:01:27 +0200 2011harry pts/6 s54d.acme.com Mon Jul 14 07:56:20 +0200 2011carol pts/4 s53e.acme.com Mon Jul 14 07:57:05 +0200 2011carlos pts/5 s54a.acme.com Mon Jul 14 08:07:41 +0200 2011

所以,你已经在这里做了一个很好的报告,告诉人们上次登录你老板的时间。好吧,直到你意识到你已经证明你(fred)在08:45登录,在你应该上班之后的三点五分钟。不用担心。Sed也可以解决你晚睡的习惯。我们所要做的就是用08代替07,看起来你是一个真正的得分手。

码:

cat last_logins sed 's/08/07/g' > last_logins2

你所做的是使用's'选项(替代)来改变每个08到07的实例。所以现在看起来你是在7:45进来的。你现在是多么吸引人!唯一的问题是你在整个文件中做了这些改变。这将改变萨拉和卡洛斯的登录时间,以及分别为7:01和7:07。他们看起来像真正的早起的鸟!这可能会引起怀疑,所以你需要一种方法来改变只显示你的(fred)登录行的08。再次,我们sed将来救援。

码:

sed '/fred/s/08/07/g'

而sed将确保只有包含fred的行被改为07.sed

,当然不仅仅是一个文本替换工具(以及一种隐藏你在周一过度睡眠的倾向的方法)。让我们回到以前的例子,寻找基于MS Windows的蠕虫攻击我们的Web服务器。sed实际上可以比grep做得更好。假设你想在7月份看所有的CodeRed点击,你可以这样做:

码:

cat access sed '/default.ida/!d; //Jul/!d' > MS_Exploits_July

我们之前用来删除文本的'd'选项可以用它前面的感叹号来查找文本。

相反,您可能希望从正常的网络流量中获得一份打印,无需Windows的所有漏洞。这就是简单的'd'又派上用场的地方。

码:

cat access sed '/^./d' > normal_traffic

这将消除少于200个字符的任何行,这意味着它将显示大多数正常文件的请求,而不是更长的CodeRed或Nimda命中。现在,使用反向逻辑,我们现在通过分析长度超过200个字符的命中,具有不同的CodeRed / Nimda方法。为此,我们将做一些修改:

码:

cat access sed -n '/^./p' > MS_exploits

与这个例子不同的是-n选项。这告诉sed将其操作限制在指定为'p'的其他选项,这意味着模式。换句话说,限制你显示的内容匹配220个字符或更长的模式。

有更多的方法可以使用sed来更改文件。了解更多关于sed的最好方法之一是看看别人是如何使用它,并从他们的例子中学习。如果你去Google并输入:+ sed + one liners,你可以得到各种sed可以使用的例子。这是一个很好的方法来打磨你的技能。

使用UniqUniq是清除文件中无用信息的好工具。可以这么说,这就是把麦子和糠separating分开的Unix / Linux方法。假设你参与了某种实验,你必须观察一些行为并报告。假设你正在观察某人的睡眠习惯。你必须每隔10分钟看一个人睡觉并报告,或者每当有变化的时候报告。你可以坐在你的终端前面发出这个命令,例如:

码:

echo `date +%y-%m-%d_AT_%T` No changes >> sleep_experiment_43B

而当你看到一些变化,你可以发出这个命令:

码:

echo `date +%y-%m-%d_AT_%T` subject moved right arm >> sleep_experiment_43B

你最终会看到一个如下所示的文件:

码:

03-08-09_AT_23:10:16 No change03-08-09_AT_23:20:24 No change03-08-09_AT_23:30:29 No change03-08-09_AT_23:40:31 No change03-08-09_AT_23:50:33 No change03-08-09_AT_00:00:34 No change03-08-09_AT_00:10:35 No change03-08-09_AT_00:20:37 No change03-08-09_AT_00:30:05 subject rolled over03-08-09_AT_00:40:12 No change03-08-09_AT_00:50:13 No change03-08-09_AT_01:00:50 subject moved left leg03-08-09_AT_01:10:17 No change03-08-09_AT_01:20:18 No change03-08-09_AT_01:30:19 No change03-08-09_AT_01:40:20 No change03-08-09_AT_01:50:47 subject moved right arm03-08-09_AT_02:00:11 No change03-08-09_AT_02:10:20 subject scratched nose

如果这个文件一直持续到07:00,当主题最终被唤醒的时候,你可能会有很多条目没有改变,这是相当无趣的。如果你只想看到睡眠行为的变化呢?Uniq是你的工具。Uniq将向您显示具有不同信息的“独特”线条或线条。你可能会想:但是所有的线都是独一无二的。这是正确的。所有的时间都不一样,但我们可以在命令行上进行调整。

码:

uniq -f 1 sleep_experiment_43B

这告诉uniq跳过第一个字段,这是数据字段,只是列出了唯一的字段。你最终会得到这样的结果:

码:

03-08-09_AT_23:10:16 No change03-08-09_AT_00:30:05 subject rolled over03-08-09_AT_01:00:50 subject moved left leg03-08-09_AT_01:50:47 subject moved right arm03-08-09_AT_02:10:20 subject scratched nose

现在你可能会说:我想运行Linux机器,而不是进行睡眠实验。我如何在这些方面使用“uniq”?那么,让我们回到我们上次登录时查找用户的例子。如果你还记得,lastlog为我们提供了这些信息,但它也列出了不是真正的人的用户。我们通过调用sed将其缩小为真正的登录用户。唯一的缺点是我们只有用户登录。如果你想看到所有的真实用户是否已经登录,你可以这样做:

码:

lastlog uniq -f 4

lastlog输出的第四个字段是指示**从未登录**的字段,所以这将查找所有真实用户,无论他们是否已经登录。这对于找出哪些用户实际上使用了我们的系统是很好的。有些人给了shell帐户,然后他们从不使用它们。你可以把这些人除掉。

排序出

另一个文本操作工具,将派上用场是排序。这个工具接受一个文本文件或另一个命令的输出,并根据选择的选项“排序”(按照某种顺序排列)。使用没有任何选项的排序将只是按顺序放置文件的行。让我们想象一下,你有一个购物清单,看起来像这样:

码:

chocolate ketchupdetergentcola chicken mustardbleachhamricebreadcroissantsice-creamhamburgerscookiesspaghetti

为了把这个按字母顺序排列,你只需输入:

码:

sort grocery_list

这会给你一个漂亮的名单,从漂白开始,以意大利面条结束。但是假设你比一般的购物者更聪明,而且你还记下了物品的位置,节省了你的时间。假设你的列表如下所示:

码:

chocolate aisle 3ketchup aisle 9detergent aisle 6cola aisle 5chicken meat deptmustard aisle 9bleach aisle 6ham deli counterrice aisle 4bread aisle 1croissants aisle 1ice-cream aisle 2hamburgers meat deptcookies aisle 3spaghetti aisle 4

为了更快地到达超市,您可以按如下方式对列表的第二列进行排序:

码:

sort +2 grocery_list

+2(+ [列])表示根据第二列进行排序。现在,您将按部分对所有内容进行很好的排序:

码:

bread aisle 1croissants aisle 1ice-cream aisle 2chocolate aisle 3cookies aisle 3rice aisle 4spaghetti aisle 4cola aisle 5bleach aisle 6detergent aisle 6ketchup aisle 9mustard aisle 9ham deli counterchicken meat depthamburgers meat dept

再一次,你可能会说:作为一个更有效的购物者会帮助我执行系统管理任务吗?答案是:是的,当然!但让我们看看另一个例子,我们的系统必须如此。

tail是另一个系统上更有用的命令之一。尾部会显示一个文件的最后10行。但是如果你用“猫”来排序和“更多”,你会得到一个交互式的尾巴(我无法抗拒)。

码:

cat /var/log/mail.log sort -r more

-r选项代表反向,所以在这里将会看到邮件服务器日志中最近的条目。当你按下输入键时,你将开始进入较旧的输入。

切入正题

有时候程序的输出会给你太多的信息。你将不得不削减一些。这就是节目的切入点。之前我们看到了如何获取网站访问者的IP地址。这是一个复习,有一个转折。

码:

cat access cut -c1-16 > IP_visitors

这会得到一个包含所有IP地址的文件。我们会在一分钟后回到这个。

当然还有其他的实际用途。有一天,客户要求我让系统上的用户使用Hylafax,这是Linux的传真服务器。让用户访问Hylafax的要求之一是知道他或她的用户ID或UID。这些信息位于/ etc / passwd中,有一个快速的方法来获取它:

码:

cat /etc/passwd grep bob cut -f1,3 -d":"

基本上我们所做的就是grep用户bob出passwd文件,并通过它来剪切并取第一个和第三个(1,3)由冒号分隔(分隔-d)的字段。结果是这样的:

bob:1010

User 'bob' has a UID of 1010.

我们再来看看我们的Apache weblog例子。我们可以结合我们学到的一些文本处理工具,看看有多少个唯一的IP地址访问过我们的网站。

码:

cat access cut -f1-2 -d" " sort uniq wc -l

这是Unix做事的一个很好的例子。我们已经删除了第一个字段(-f1-2 - 仅显示了由空格-d分隔的字段1到2)“)。我们管它来排序,这使得它们按数字顺序排列。然后,uniq工具只显示“唯一”的IP地址。最后,'wc -l'代表行数。你真的不得不问自己:用普通的文字处理器或文本编辑器获取这些信息会花费多少钱?

关注吕田论坛获取更多资讯

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180113G0HIJZ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券