首頁 > 軟體

在 Unix 系統上查詢資料的最佳工具和技巧

2020-06-16 17:51:18

有時候在 Unix 系統上查詢資訊就如同大海撈針。如果重要的資訊被淹沒在大量文字中,它們也很難被注意到。目前我們中的很多人都在處理“巨量資料” —— 從數十億位元組大小的紀錄檔檔案和巨大的各種格式記錄集合中挖掘商業情報。

幸運的是,只有在兩種情況下,你才需要在成堆的資料中挖掘,繼而完成你的工作 —— 當你知道你要找什麼和當你不知道的時候。:) 最佳工具和技巧取決於你面臨兩種情況中的哪一種。

 

當你知道的時候

當你知道你要找什麼,grep 就是你的朋友,這不只是在你查詢特定文字的時候。grep 命令可以幫助你找到任意文字,特定單詞,文字模式和有上下文的文字。當你知道文字長什麼樣時,查詢它通常很簡單。grep this that 命令會顯示“that”檔案中包含“this”字串的每一行。增加 -w 選項就只會顯示那些單獨包含“this”這個單詞的行。換句話說,如果行中包含“thistle” 或 “erethism” 就不會顯出來,除非這些行也有 “this” 這個單詞。

最簡單的 grep 命令不費什麼力氣就能理解:

  1. $ grepfind poem
  2. finding meaning, finding comfort,
  3. finding someone to adore
  4. Can we find a way to be

查詢整個單詞可以通過增加 -w 選項完成:

  1. $ grep-wfind poem
  2. Can we find a way to be

查詢模式需要一點技巧。我們的第一個例子中顯示了包含“find”單詞的行,無論“find”中的“f”是大寫還是小寫:

  1. $ grep[Ff]ind poem
  2. Finding answers
  3. finding meaning, finding comfort,
  4. finding someone to adore
  5. Can we find a way to be

如果你想匹配以文字起始或結束的行,你可以使用 ^(起始)或 $(結尾)。

  1. $ grep^find poem
  2. finding meaning, finding comfort,
  3. finding someone to adore

如果你想找到包含兩個連續元音音節的單詞的行,你可以使用如下所示的“AEIOUaeiou”字元。

  1. $ grep-E "[AEIOUaeiou]{2}" poem |head-3
  2. Allour days are filled with searching
  3. wondering what we're looking for
  4. finding meaning, finding comfort,

查詢包含 9 個或者 10 個字母的字串:

  1. $ grep-E "[[:alpha:]]{9,10}" poem
  2. Allour days are filled with searching
  3. wondering what we're looking for
  4. All our days are filled with searching
  5. that makes the searching more productive

查詢一個包含 “find” 的長單詞:

  1. $ grep-E "find[^[:space:]]+" poem
  2. finding meaning, finding comfort,
  3. finding someone to adore

我們中的大多數人不會去查詢詩歌,這是顯而易見的,但我們可以使用同樣的技巧來從我們的系統檔案中獲取相關的資訊。在下面的例子裡,我們查詢”processor”這個術語,並且按照五行一組(前置兩行後置兩行)顯示出來以便提供一些上下文。如果你希望得到 9 行一組,將 -C 2 變成 -C 4 就可以了。

  1. $ grep-C 2 processor /var/log/dmesg
  2. Using ACPI (MADT)for SMP configuration information
  3. Allocating PCI resources starting at 88000000(gap:80000000:7ec00000)
  4. Detected3400.426MHz processor.
  5. Built1 zonelists.Total pages:524275
  6. Kernel command line: ro root=LABEL=/1
  7. --
  8. Inode-cache hash table entries:65536(order:6,262144 bytes)
  9. Memory:2071140k/2097100k available (2223k kernel code,24616k reserved,922k data,232kinit,1179596k highmem)
  10. Checkingifthis processor honours the WP bit even in supervisor mode...Ok.
  11. Calibrating delay loop (skipped), value calculated using timer frequency..6800.85BogoMIPS(lpj=3400426)
  12. SecurityFramework v1.0.0 initialized
  13. --
  14. CPU0:Intel(R)Xeon(TM) CPU 3.40GHz stepping 04
  15. SMP alternatives: switching to SMP code
  16. Booting processor 1/1 eip 11000
  17. CPU 1 irqstacks, hard=c0779000 soft=c0759000
  18. Initializing CPU
  19. #1
  20. --
  21. CPU1:Intel(R)Xeon(TM) CPU 3.40GHz stepping 04
  22. SMP alternatives: switching to SMP code
  23. Booting processor 2/6 eip 11000
  24. CPU 2 irqstacks, hard=c077a000 soft=c075a000
  25. Initializing CPU
  26. #2
  27. --
  28. CPU2:Intel(R)Xeon(TM) CPU 3.40GHz stepping 04
  29. SMP alternatives: switching to SMP code
  30. Booting processor 3/7 eip 11000
  31. CPU 3 irqstacks, hard=c077b000 soft=c075b000
  32. Initializing CPU
  33. #3

 

當你不知道的時候

如果你要查詢一個已知位置的文字,例如當 Perl 告訴你指令碼執行到第 73 行出現了問題,或者你正在處理檔案的第 1892 行,你可以使用sed 來顯示特定的行(我只是不喜歡數到 1892 行)。而且額外花一點點力氣,你就可以只顯示這一行。

錯誤資訊可能像這個樣子:

  1. syntax error line 73 near ”}else

你可以使用一個sed命令來顯示出問題的這行:

  1. $ sed-n 73p showvars
  2. else

好了,就是這行,但是我們也沒有比之前多知道些什麼。通過顯示前面幾行可以增加一點上下文資訊,我們就可以定位錯誤。這裡有一個類似的命令可以顯示這行和之前的十行:

  1. $ sed-n 63,73p showvars
  2. if $password eq "a_secret";
  3. {
  4. foreach $var (sort(keys(%ENV))){
  5. $val = $ENV{$var};
  6. $val =~ s|n|n|g;
  7. $val =~ s|"|"|g;
  8. print'${var}="${val}"n'
  9. };
  10. }
  11. else

哎呦!這看上去是某些人在寫 if 語句時出了問題!我們可以很容易地修復它。

你還可以使用 sed 命令來強調包含特定內容的行。在下面的命令裡,我們增加了一個 “箭頭標記” 來強調每一個包含 foreach 命令的行:

  1. $ sed'/print/{b label1; {:label1 ; s/^/# / ; s/$/ <===/ ;} }' showvars
  2. #!/bin/bash
  3. if $password eq "a_secret";
  4. {
  5. foreach $var (sort(keys(%ENV))){
  6. $val = $ENV{$var};
  7. $val =~ s|n|n|g;
  8. $val =~ s|"|"|g;
  9. #print'${var}="${val}"n'<===
  10. };
  11. }
  12. else

你可以使用類似的命令注釋掉你的 print 命令:

  1. $ sed'/print/{b label1; {:label1 ; s/^/# / ; s/$/ <===/ ;} }' showvars
  2. #!/bin/bash
  3. if $password eq "a_secret";
  4. {
  5. foreach $var (sort(keys(%ENV))){
  6. $val = $ENV{$var};
  7. $val =~ s|n|n|g;
  8. $val =~ s|"|"|g;
  9. #print'${var}="${val}"n'<===
  10. };
  11. }
  12. else

大海撈針很難,其實地毯上找針也都不容易。但是通過使用一些最常見 Unix 命令的變形,就可以很容易找到你要找的東西,甚至當你並不知道要找什麼的時候。

本文永久更新連結地址http://www.linuxidc.com/Linux/2015-10/124286.htm


IT145.com E-mail:sddin#qq.com