아래와 같이 로그 파일 수에서 디렉토리의 문자열과 일치하는 스크립트가 있습니다.
#!/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
귀하의 질문을 읽으면서 저는 항상 파일에서 특정 문자열을 검색한 다음 해당 문자열이 포함된 파일 중 하나를 보는 것을 더 쉽게 만들어 주는 간단한 스크립트를 갖고 싶다는 생각이 들었습니다. 귀하의 스크립트와 배열을 사용하라는 saga의 제안을 바탕으로 저는 제 스크립트를 만들었고 귀하의 스크립트도 완성했습니다. :)
참고: 이 스크립트는 /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
편집: 위의 스크립트는 원래 질문에 대해 완벽하게 작동하지만 Wildcard의 답변을 기반으로 작성되었으므로 내 스크립트는 빈 공간이 있는 파일을 처리하고 다양한 기능을 제공할 수 있습니다.도구선택한 파일을 열려면
내 스크립트:
#!/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