Bash

如何在 bash 中的數組值中保留文字表達式中的空格以及如何修剪排序命令的結果?

  • January 20, 2014

在搜尋日誌文件中的表達式的上下文中,我一般想知道是否有一種方法可以以某種方式量化和限定日誌的內容/var/log。特別是,用於描述錯誤情況的詞典是否符合一般預期,以及術語在日誌中有何不同。為了進一步調查並驗證這些期望,我製作了這個小腳本來檢查、計數和排序一些事情:

#!/bin/bash
# Meh - In /var/log, (1) for each file count lines which
# contain matches for expressions in the set; then, 
# (2), iterate files again and sort (all) words in a file  
# by descending frequency.

FILES="/var/log/* /var/log/**/* /var/log/**/**/*"
WORDS=(error fail.* wrong bad break panic abort.* disaster problem issue 'couldn'\''t' 'didn'\''t' 'wasn'\''t' 'shouldn'\''t' 'isn'\''t' 'don'\''t' "is'\ 'not" 'did\ not' die.* crash.* dump.* seg.* bug.* report.* status)

# Header section 1
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
printf 'Matches for expressions in set\n' 
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -

# (1)
for f in $FILES
do
   for w in ${WORDS[@]} 
   do 
       echo -n "$f [$w]:"
       grep -aci $w $f 2>/dev/null
   done
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
done

# Header section 2
printf 'Sorted occurences for all words in a file\n' 
printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -

# (2)
for f in $FILES
do
   echo "[total number of lines: $(wc -l $f 2>/dev/null)]"
   cat $f 2>/dev/null | tr -c '[:alnum:]' '[\n*]' | tr -d '[:digit:]' | sort -f | uniq -ci | sort -fnr
   printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -
done

exit

無論多麼粗糙和有缺陷,它都達到了讓我瞥見頻率並在一定程度上驗證集合的目的。例如,這是dmesg我係統上的一些範例輸出:

/var/log/dmesg [error]:27
/var/log/dmesg [fail.*]:7
/var/log/dmesg [wrong]:0
/var/log/dmesg [bad]:0
/var/log/dmesg [break]:0
/var/log/dmesg [panic]:1
/var/log/dmesg [abort.*]:0
/var/log/dmesg [disaster]:0
/var/log/dmesg [problem]:0
/var/log/dmesg [issue]:0
/var/log/dmesg [couldn't]:2
/var/log/dmesg [didn't]:0
/var/log/dmesg [wasn't]:0
/var/log/dmesg [shouldn't]:0
/var/log/dmesg [isn't]:0
/var/log/dmesg [don't]:0
/var/log/dmesg [is'\]:/var/log/dmesg ['not]:0     <------
/var/log/dmesg [did\]:/var/log/dmesg [not]:14     <------
/var/log/dmesg [die.*]:0
/var/log/dmesg [crash.*]:0
/var/log/dmesg [dump.*]:0
/var/log/dmesg [seg.*]:0
/var/log/dmesg [bug.*]:3
/var/log/dmesg [report.*]:1
/var/log/dmesg [status]:28

   [total number of lines: 1059 /var/log/dmesg]
     14784 
       306 usb
       220 pci
       133 x
       128 hub
       116 acpi
       113 d
       109 mem
        95 a
        94 uhci
        76 hcd
        76 device
        73 bus
        56 io
        55 to
        54 port
        54 e
        54 ata
        53 c
        51 power
        48 interface
        47 registered
        46 ehci
        40 system
        40 for
        38 new
        37 sda
        37 bridge
        36 on
        36 irq
        34 type
        34 reset
        34 probe
        34 nouveau
        33 v
        33 sd
        31 reserved
        30 memory
        29 f
        27 ports
        27 found
        27 error
        27 and
        26 resource
        26 reg
        26 input
        26 driver
        25 id
        25 i
        23 window
        23 disabled
        22 xc
        22 status
        22 from
        22 drm
        22 bit
        ...

“錯誤”是我的設置中最重要的“問題詞”,或者很多與硬體相關的條目出現在dmesg.

問題

  • 如何在數組值列表中保留由兩個單詞(“is not”、“did not”)組成的文字表達式的值中的空間?嘗試了 ‘did’\040’not’ 或 “did’'not” 以及許多變體。不確定如何應用此問答中的資訊。

  • 當第二個循環(2)最終輸出日誌中每個唯一出現的單詞時,如何限制它的範圍或我應該如何丟棄:

    • 由單個字元組成的輸出?
    • 由單個事件組成的輸出?
  • 是否有任何視覺化呈現輸出的建議,或者是否有工具可以為搜尋或格式化計數和單詞數據提供更多功能?

使用 shell 變數時,您可以通過用雙引號將 shell 變數括起來來保留空格字元(更準確地說,防止值根據欄位分隔符拆分為單詞,這些字元在 $IFS shell 變數中列舉)。

for w in "${WORDS[@]}" 
do 
 echo -n "$f [$w]:"
 grep -aci "$w" $f 2>/dev/null
done

$f如果您遇到帶有空格的文件名,也可以用引號括起來。)

當第二個循環(2)最終輸出日誌中每個唯一出現的單詞時,如何限制它的範圍或我應該如何丟棄:

由單個字元組成的輸出?

grep ..在管道中添加以僅包含具有 2 個或更多字元的行。

由單個事件組成的輸出?

添加-duniq管道中,這樣它就只會顯示重複的行。

cat $f 2>/dev/null | tr -c '[:alnum:]' '[\n*]' | tr -d '[:digit:]' | sort -f | grep .. | uniq -dci | sort -fnr

是否有任何視覺化呈現輸出的建議,或者是否有工具可以為搜尋或格式化計數和單詞數據提供更多功能?

有很多應用程序可以掃描和總結日誌文件中有趣的事件,有些是免費的,有些是商業的。我不確定我們是否可以提供廣泛的建議,但如果您可以提供您想提出的查詢範例或您想查看的輸出格式,也許我們可以回答這些類型的問題。

引用自:https://unix.stackexchange.com/questions/110100