나는 일부 문자열이 포함된 파일을 더 자주 찾는다는 것을 인정합니다.
현재 나는 이렇게 합니다:
grep -rl string1 | xargs grep -l string2 | xargs grep -l string3
이 작업을 수행할 수 있는 도구가 있나요?
이는 또는 grep
입니다 .string1
string2
string3
grep -rl -e string1 -e string2 -e string3
string1
string2
and 를 포함하는 파일을 원 string3
하지만 반드시 같은 줄에 있을 필요는 없습니다.
grep
어쩌면 현대인 중 한 사람( ) ag/ack/rg/sift
이 이것을 할 수 있을까요?
답변1
다음과 같이 사용할 수 있습니다 grep
.
grep -rzlP '(?s)(?=.*?string1)(?=.*?string2)(?=.*?string3)' .
(?s)
알려진 "dot-all"은 다음과 같습니다.grep점이.
새 줄 문자와도 일치하도록 허용합니다.\n
(?=.*?pattern)
: 정방향 예측은.
0번 이상 나타나고*
욕심이 없는 모든 문자와 일치하며 그 뒤에 패턴(string1
,string2
, ...)이 옵니다.
다음과 같은 함수를 만들 수 있습니다(POSIX bash
& zsh
).
mgrep() { eval grep -rzlP $(printf ''\''(?s)';
printf '(?=.*?'\''"$%d"'\'')' $(eval echo {1..$#}); printf ''\''') . ; }
그런 다음 다음과 같이 호출하면 현재 작업 디렉터리의 모든 내용이 포함된 파일을 재귀적으로 찾습니다.무늬존재하다.
mgrep string1 string2 string3
grep
또한 기본적으로 지원하는 모든 유형의 패턴을 처리합니다 (grep
필요에 맞게 기능의 옵션을 미리 조정하세요.).
mgrep string 'pattern with space' '\d+' [0-9] [...]
답변2
agrep
( 원본비슷한grep
, )의 것이 아니라 tre
할 수 있습니다
agrep -ld '$x' 'pattern1;pattern2;pattern3'
일치할 수 없는 정규식( $x
끝 뒤에 오는 것)을 구분 기호로 사용합니다.
( 디렉토리의 모든 파일을 재귀적으로 검색하려면 find
또는 재귀 glob을 사용하십시오.)zsh
그러나 패턴은 각 파일의 모든 줄이 아니라 파일의 전체 내용과 일치합니다.
gawk를 사용하여 스크립트를 작성할 수 있습니다.
PATTERNS='pattern1;pattern2;pattern3' gawk -e '
BEGIN{n = split(ENVIRON["PATTERNS"], a, ";")}
BEGINFILE{for (i in a) p[a[i]]; found = 0}
{
for (i in p)
if ($0 ~ i) {
if (++found == n) {print FILENAME; nextfile}
delete p[i]
}
}' -E /dev/null file1 file2...
(느리지만).
답변3
αГsнιn의 답변에 따르면:
mgrep() {
grep -rzlP "(?s)$(printf "(?=.*?%s)" "$@")" .
}
mgrep string1 string2 string3
답변4
다음 제안은 간단하지만 더 효과적이고 강력할 수 있습니다.
#!/bin/bash
tab=(one three five)
# grep_all's return status indicates if all patterns have at least
# one matching result in the text file specified as argument.
grep_all()
{
local -n patterns=$1 # allows to refer to an array
local file=$2
# abort if a pattern is not found
for pattern in "${patterns[@]}"; do
if ! grep -q -e "$pattern" "$file"; then
return 1
fi
done
}
grep_all tab file.txt
echo $?