有时候在 Unix 系统上查找信息就如同大海捞针。如果重要的信息被淹没在大量文本中,它们也很难被注意到。目前我们中的很多人都在处理“大数据” —— 从数十亿字节大小的日志文件和巨大的各种格式记录集合中挖掘商业情报。
幸运的是,只有在两种情况下,你才需要在成堆的数据中挖掘,继而完成你的工作 —— 当你知道你要找什么和当你不知道的时候。:) 最佳工具和技巧取决于你面临两种情况中的哪一种。
当你知道的时候
当你知道你要找什么,grep 就是你的朋友,这不只是在你查找特定文本的时候。grep 命令可以帮助你找到任意文本,特定单词,文本模式和有上下文的文本。当你知道文本长什么样时,查找它通常很简单。grep this that 命令会显示“that”文件中包含“this”字符串的每一行。增加 -w 选项就只会显示那些单独包含“this”这个单词的行。换句话说,如果行中包含“thistle” 或 “erethism” 就不会显出来,除非这些行也有 “this” 这个单词。
最简单的 grep 命令不费什么力气就能理解:
1
2
3
4
|
$
grep
find
poem finding
meaning, finding comfort, finding
someone to adore Can
we find
a way to be |
查找整个单词可以通过增加 -w 选项完成:
1
2
|
$
grep
-w find
poem Can
we find
a way to be |
查找模式需要一点技巧。我们的第一个例子中显示了包含“find”单词的行,无论“find”中的“f”是大写还是小写:
1
2
3
4
5
|
$
grep
[Ff]ind poem Finding
answers finding
meaning, finding comfort, finding
someone to adore Can
we find
a way to be |
如果你想匹配以文本起始或结束的行,你可以使用 ^(起始)或 $(结尾)。
1
2
3
|
$
grep
^ find
poem finding
meaning, finding comfort, finding
someone to adore |
如果你想找到包含两个连续元音音节的单词的行,你可以使用如下所示的“AEIOUaeiou”字符。
1
2
3
4
|
$
grep
-E "[AEIOUaeiou]{2}"
poem | head
-3 All
our days are filled with searching wondering
what we're looking for finding
meaning, finding comfort, |
查找包含 9 个或者 10 个字母的字符串:
1
2
3
4
5
|
$
grep
-E "[[:alpha:]]{9,10}"
poem All
our days are filled with searching wondering
what we're looking for All
our days are filled with searching that
makes the searching more
productive |
查找一个包含 “find” 的长单词:
1
2
3
|
$
ann> grep
-E "find[^[:space:]]+"
poem finding
meaning, finding comfort, finding
someone to adore |
我们中的大多数人不会去查找诗歌,这是显而易见的,但我们可以使用同样的技巧来从我们的系统文件中获取相关的信息。在下面的例子里,我们查找”processor”这个术语,并且按照五行一组(前置两行后置两行)显示出来以便提供一些上下文。如果你希望得到 9 行一组,将 -C 2 变成 -C 4 就可以了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
$
grep
-C 2 processor /var/log/dmesg Using
ACPI (MADT) for
SMP configuration information Allocating
PCI resources starting at 88000000 (gap: 80000000:7ec00000) Detected
3400.426 MHz processor. Built
1 zonelists. Total pages: 524275 Kernel
command
line: ro root=LABEL= /1 -- Inode-cache
hash
table entries: 65536 (order: 6, 262144 bytes) Memory:
2071140k /2097100k
available (2223k kernel code, 24616k reserved, 922k data, 232k init, 1179596k highmem) Checking
if
this processor honours the WP bit even in
supervisor mode... Ok. Calibrating
delay loop (skipped), value calculated using timer frequency.. 6800.85 BogoMIPS (lpj=3400426) Security
Framework v1.0.0 initialized -- CPU0:
Intel(R) Xeon(TM) CPU 3.40GHz stepping 04 SMP
alternatives: switching to SMP code Booting
processor 1 /1
eip 11000 CPU
1 irqstacks, hard=c0779000 soft=c0759000 Initializing
CPU #1 -- CPU1:
Intel(R) Xeon(TM) CPU 3.40GHz stepping 04 SMP
alternatives: switching to SMP code Booting
processor 2 /6
eip 11000 CPU
2 irqstacks, hard=c077a000 soft=c075a000 Initializing
CPU #2 -- CPU2:
Intel(R) Xeon(TM) CPU 3.40GHz stepping 04 SMP
alternatives: switching to SMP code Booting
processor 3 /7
eip 11000 CPU
3 irqstacks, hard=c077b000 soft=c075b000 Initializing
CPU #3 |
当你不知道的时候
如果你要查找一个已知位置的文本,例如当 Perl 告诉你脚本执行到第 73 行出现了问题,或者你正在处理文件的第 1892 行,你可以使用sed 来显示特定的行(我只是不喜欢数到 1892 行)。而且额外花一点点力气,你就可以只显示这一行。
错误信息可能像这个样子:
1
|
“syntax
error line 73 near ”} else “
” |
你可以使用一个sed命令来显示出问题的这行:
1
2
|
$
sed
-n 73p showvars else |
好了,就是这行,但是我们也没有比之前多知道些什么。通过显示前面几行可以增加一点上下文信息,我们就可以定位错误。这里有一个类似的命令可以显示这行和之前的十行:
1
2
3
4
5
6
7
8
9
10
11
|
sed
-n 63,73p showvars if
$password eq
"a_secret" ; { foreach
$var ( sort (keys(%ENV)))
{ $val
= $ENV{$var}; $val
=~ s|n|n|g; $val
=~ s| "|" |g; print
'${var}="${val}"n' }; } else |
哎呦!这看上去是某些人在写 if 语句时出了问题!我们可以很容易地修复它。
你还可以使用 sed 命令来强调包含特定内容的行。在下面的命令里,我们增加了一个 “箭头标记” 来强调每一个包含 foreach 命令的行:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$
sed
'/print/{b label1; {:label1 ; s/^/# / ; s/$/ <===/ ;} }'
showvars #!/bin/bash if
$password eq
"a_secret" ; { foreach
$var ( sort (keys(%ENV)))
{ $val
= $ENV{$var}; $val
=~ s|n|n|g; $val
=~ s| "|" |g; #
print '${var}="${val}"n' <=== }; } else |
你可以使用类似的命令注释掉你的 print 命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
$
sed
'/print/{b label1; {:label1 ; s/^/# / ; s/$/ <===/ ;} }'
showvars #!/bin/bash if
$password eq
"a_secret" ; { foreach
$var ( sort (keys(%ENV)))
{ $val
= $ENV{$var}; $val
=~ s|n|n|g; $val
=~ s| "|" |g; #
print '${var}="${val}"n' <=== }; } else |
大海捞针很难,其实地毯上找针也都不容易。但是通过使用一些最常见 Unix 命令的变形,就可以很容易找到你要找的东西,甚至当你并不知道要找什么的时候。
转载自:http://blog.jobbole.com/92811/