다음과 같이 여러 로그 파일의 디렉터리 문자열을 일치시키는 스크립트가 있습니다.
#!/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