有時候在 Unix 系統上查找信息就如同大海撈針。如果重要的信息被淹沒在大量文本中,它們也很難被注意到。目前我們中的很多人都在處理“大數據” —— 從數十億字節大小的日志文件和巨大的各種格式記錄集合中挖掘商業情報。
幸運的是,只有在兩種情況下,你才需要在成堆的數據中挖掘,繼而完成你的工作 —— 當你知道你要找什麼和當你不知道的時候。:) 最佳工具和技巧取決於你面臨兩種情況中的哪一種。
當你知道你要找什麼,grep 就是你的朋友,這不只是在你查找特定文本的時候。grep 命令可以幫助你找到任意文本,特定單詞,文本模式和有上下文的文本。當你知道文本長什麼樣時,查找它通常很簡單。grep this that 命令會顯示“that”文件中包含“this”字符串的每一行。增加 -w 選項就只會顯示那些單獨包含“this”這個單詞的行。換句話說,如果行中包含“thistle” 或 “erethism” 就不會顯出來,除非這些行也有 “this” 這個單詞。
最簡單的 grep 命令不費什麼力氣就能理解:
$ grepfind poem
finding meaning, finding comfort,
finding someone to adore
Can we find a way to be
查找整個單詞可以通過增加 -w 選項完成:
$ grep-wfind poem
Can we find a way to be
查找模式需要一點技巧。我們的第一個例子中顯示了包含“find”單詞的行,無論“find”中的“f”是大寫還是小寫:
$ grep[Ff]ind poem
Finding answers
finding meaning, finding comfort,
finding someone to adore
Can we find a way to be
如果你想匹配以文本起始或結束的行,你可以使用 ^(起始)或 $(結尾)。
$ grep^find poem
finding meaning, finding comfort,
finding someone to adore
如果你想找到包含兩個連續元音音節的單詞的行,你可以使用如下所示的“AEIOUaeiou”字符。
$ grep-E "[AEIOUaeiou]{2}" poem |head-3
Allour days are filled with searching
wondering what we're looking for
finding meaning, finding comfort,
查找包含 9 個或者 10 個字母的字符串:
$ grep-E "[[:alpha:]]{9,10}" poem
Allour 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” 的長單詞:
$ grep-E "find[^[:space:]]+" poem
finding meaning, finding comfort,
finding someone to adore
我們中的大多數人不會去查找詩歌,這是顯而易見的,但我們可以使用同樣的技巧來從我們的系統文件中獲取相關的信息。在下面的例子裡,我們查找”processor”這個術語,並且按照五行一組(前置兩行後置兩行)顯示出來以便提供一些上下文。如果你希望得到 9 行一組,將 -C 2 變成 -C 4 就可以了。
$ grep-C 2 processor /var/log/dmesg
Using ACPI (MADT)for SMP configuration information
Allocating PCI resources starting at 88000000(gap:80000000:7ec00000)
Detected3400.426MHz processor.
Built1 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,232kinit,1179596k highmem)
Checkingifthis processor honours the WP bit even in supervisor mode...Ok.
Calibrating delay loop (skipped), value calculated using timer frequency..6800.85BogoMIPS(lpj=3400426)
SecurityFramework 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 行)。而且額外花一點點力氣,你就可以只顯示這一行。
錯誤信息可能像這個樣子:
“syntax error line 73 near ”}else“”
你可以使用一個sed命令來顯示出問題的這行:
$ sed-n 73p showvars
else
好了,就是這行,但是我們也沒有比之前多知道些什麼。通過顯示前面幾行可以增加一點上下文信息,我們就可以定位錯誤。這裡有一個類似的命令可以顯示這行和之前的十行:
$ 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 命令的行:
$ 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 命令:
$ 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 命令的變形,就可以很容易找到你要找的東西,甚至當你並不知道要找什麼的時候。