로그 파일에서 문자열을 찾는 쉘 스크립트

로그 파일에서 문자열을 찾는 쉘 스크립트

다음과 같이 여러 로그 파일의 디렉터리 문자열을 일치시키는 스크립트가 있습니다.

#!/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

그냥 select( bash내장)을 사용하세요.

$ 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

귀하의 질문을 읽으면서 파일에서 특정 문자열을 보다 쉽게 ​​검색하고 해당 문자열이 포함된 파일 중 하나를 볼 수 있도록 항상 간단한 스크립트를 원했다는 사실을 떠올렸습니다. 귀하의 스크립트와 배열 사용에 대한 시리즈의 제안을 바탕으로 저는 스크립트를 작성하고 스크립트를 완성했습니다. :)

참고: 이 스크립트는 /bin/sh가 아닌 /bin/bash용입니다. 왜냐하면 배열이 /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

관련 정보