@StephaneChazelas가 제안한pcregrep
대로 사용하면 됩니다 .
이것은 작동해야합니다 :
$ find . -name "*.cpp" |
while IFS= read -r file; do
grep -A 3 Foo "$file" | grep -q Bar || echo "$file";
done
아이디어는 grep의 -A
스위치 를 사용 하여 일치하는 줄과 N 다음 줄을 출력하는 것입니다. 그런 다음 a를 통해 결과를 전달하고 grep Bar
일치하지 않으면 (종료> 0) 파일 이름을 에코합니다.
빈 파일 이름 (공백, 줄 바꿈 또는 기타 이상한 문자가 없음)을 알고있는 경우 다음과 같이 단순화 할 수 있습니다.
$ for file in $(find . -name "*.cpp"); do
grep -A 3 Foo "$file" | grep -q Bar || echo "$file";
done
예를 들면 다음과 같습니다.
terdon@oregano foo $ cat a.cpp
1 Foo
2 qwerty
3 qwerty
terdon@oregano foo $ cat b.cpp
1 Foo
2 Bar
3 qwerty
terdon@oregano foo $ cat c.cpp
1 Foo
2 qwerty
3 qwerty
4 qwerty
5. Bar
terdon@oregano foo $ for file in $(find . -name "*.cpp"); do grep -A 3 Foo "$file" | grep -q Bar || echo "$file"; done
./c.cpp
./a.cpp
참고 c.cpp
포함에도 불구하고 반환되는 Bar
행이 함께 있기 때문에 Bar
3 개 이상의 행 다음입니다 Foo
. 전달 된 값을 변경하여 검색하려는 행 수를 제어합니다 -A
.
$ for file in $(find . -name "*.cpp"); do
grep -A 10 Foo "$file" | grep -q Bar || echo "$file";
done
./a.cpp
다음은 더 짧은 것입니다 (을 사용한다고 가정 bash
).
$ shopt -s globstar
$ for file in **/*cpp; do
grep -A 10 Foo "$file" | grep -q Bar || echo "$file";
done
중대한
주석에서 Stephane Chazelas가 지적했듯이 위의 솔루션은 전혀 포함되지 않은 파일도 인쇄합니다 Foo
. 이것은 이것을 피합니다 :
for file in **/*cpp; do
grep -qm 1 Foo "$file" &&
(grep -A 3 Foo "$file" | grep -q Bar || echo "$file");
done