Shell 腳本在日誌檔案中尋找字串

Shell 腳本在日誌檔案中尋找字串

我有一個腳本,它與多個日誌檔案中的目錄中的字串相匹配,如下所示:

#!/bin/sh
# Collect Customer ID as input
read -p "Enter Customer ID: " custid
echo "Searched customer ID $custid found in following logs: "
# Find the customer id as string in specified directory
find /usr/local/tomcat9/logs/ -type f -exec grep -l "$custid" {} \;

這將輸出包含搜尋字串的日誌檔案清單。例如:

Enter Customer ID: 2001NM-100313
Searched customer ID 2001NM-100313 found in following logs:
/usr/local/tomcat9/logs/localhost_access_log.2017-10-04.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-07-11.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-11-02.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-08-09.txt
/usr/local/tomcat9/logs/localhost_access_log.2017-06-11.txt

我想要這個輸出作為列表,如下所示:

1. /usr/local/tomcat9/logs/localhost_access_log.2017-10-04.txt
2. /usr/local/tomcat9/logs/localhost_access_log.2017-07-11.txt
3. /usr/local/tomcat9/logs/localhost_access_log.2017-11-02.txt
4. /usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt
5. /usr/local/tomcat9/logs/localhost_access_log.2017-08-09.txt
6. /usr/local/tomcat9/logs/localhost_access_log.2017-06-11.txt

它會要求輸入數字 1/2/3/4/5/6,這將開啟該編號的文件,即;如果我按 4 它會發送命令

vim /usr/local/tomcat9/logs/localhost_access_log.2017-09-11.txt

並且將在整個文件中搜尋字串“2001NM-100313”。

我的目標是從日誌檔案中讀取包含此字串的整行(可能有多個行包含該字串),可能有多個日誌檔案包含此字串和多個日期,我需要選擇任何帶日期的文件並閱讀日誌。

答案1

只需使用selectbash內建)。

$ help select
select: select NAME [in WORDS ... ;] do COMMANDS; done
    The WORDS are expanded, generating a list of words.  The
    set of expanded words is printed on the standard error, each
    preceded by a number.  If `in WORDS' is not present, `in "$@"'
    is assumed.  The PS3 prompt is then displayed and a line read
    from the standard input.  If the line consists of the number
    corresponding to one of the displayed words, then NAME is set
    to that word.  If the line is empty, WORDS and the prompt are
    redisplayed.  If EOF is read, the command completes.  Any other
    value read causes NAME to be set to null.  The line read is saved
    in the variable REPLY.  COMMANDS are executed after each selection
    until a break command is executed.
$

所以你想要的程式碼可能是:

read -p 'Enter Customer ID: ' custid
select f in $(find /usr/local/tomcat9/logs -type f -exec grep -q -e "$custid" {} \; -print); do
  vim "$f"
done

請注意,如果您的檔案名稱包含空格,則會中斷。也可以看看:


但是,如果您select直接從 呼叫內建函數find,這將輕鬆處理空格。所以下面的其實更好在所有情況下我都能想到:

read -p 'Enter customer ID: ' custid
find /usr/local/tomcat9/logs -type f -exec grep -qe "$custid" {} \; -exec bash -c '
  select f; do vim "$f"; done' find-sh {} +

答案2

閱讀你的問題提醒我總是想要一個簡單的腳本,這樣我可以更輕鬆地在文件中搜尋特定字串,然後查看包含該字串的文件之一。根據您的腳本和 saga 使用數組的建議,我創建了我的腳本並完成了您的腳本。 :)

請注意:這個腳本是/bin/bash,而不是/bin/sh,因為我不知道如何讓數組在/bin/sh中工作...

你的腳本:

#!/bin/bash
# Collect Customer ID as input
read -p "Enter Customer ID: " custid
echo "Searched customer ID $custid found in following logs: "
# Find the customer id as string in specified directory

arr=( $(find /usr/local/tomcat9/logs/ -type f -exec grep -l "$custid" {} \; | sort -r) )

if [ ${#arr[@]} -eq 0 ]; then
    echo "No matches found."
else
    arr+=('Quit')
    select opt in "${arr[@]}"
    do
        case $opt in
            "Quit")
                break
                ;;
            *)
                vim $opt
                break
                ;;
        esac
    done
fi

編輯:雖然上面的腳本對於原始問題來說可以完美工作,但我已經建立在通配符的答案之上,因此我的腳本可以處理帶有空格的文件並提供各種工具開啟選定的文件。

我的腳本:

#!/bin/bash
# Find string in files of given directory (recursively)

read -p "Enter search string: " text
read -p "Enter directory: " directory

#arr=( $(find $directory -type f -exec grep -l "$text" {} \; | sort -r) )
#find $directory -type f -exec grep -qe "$text" {} \; -exec bash -c '

file=$(find $directory -type f -exec grep -qe "$text" {} \; -exec bash -c 'select f; do echo $f; break; done' find-sh {} +;)

if [ -z "$file" ]; then
    echo "No matches found."
else
    echo "select tool:"
    tools=("nano" "less" "vim" "quit")
    select tool in "${tools[@]}"
    do
        case $tool in
            "quit")
                break
                ;;
            *)
                $tool $file
                break
                ;;
        esac
    done
fi

相關內容