Aldırma, sadece kullanmak pcregrep
olarak önerilen @StephaneChazelas tarafından.
Bu çalışmalı:
$ find . -name "*.cpp" |
while IFS= read -r file; do
grep -A 3 Foo "$file" | grep -q Bar || echo "$file";
done
Fikir, -A
eşleşen satırları ve aşağıdaki N satırını çıkarmak için grep anahtarını kullanmaktır . Daha sonra sonucu birgrep Bar
ve bu eşleşmezse (exit> 0), dosyanın adını yankılarsınız.
Aklı başında dosya adlarınız olduğunu (boşluk, yeni satır veya başka garip karakterler olmadığını) biliyorsanız, şunları basitleştirebilirsiniz:
$ for file in $(find . -name "*.cpp"); do
grep -A 3 Foo "$file" | grep -q Bar || echo "$file";
done
Örneğin:
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
İçerdiği çizgiye 3 satırdan fazla olduğu için c.cpp
içermesine rağmen döndürüldüğünü unutmayın . Geçmek istediğiniz değeri değiştirerek aramak istediğiniz satır sayısını kontrol edersiniz :Bar
Bar
Foo
-A
$ for file in $(find . -name "*.cpp"); do
grep -A 10 Foo "$file" | grep -q Bar || echo "$file";
done
./a.cpp
İşte daha kısa olanı (kullandığınız varsayılarak bash
):
$ shopt -s globstar
$ for file in **/*cpp; do
grep -A 10 Foo "$file" | grep -q Bar || echo "$file";
done
ÖNEMLİ
Stephane Chazelas'ın yorumlarda belirttiği gibi, yukarıdaki çözümler de hiç içermeyen dosyalar basacaktır Foo
. Bu bundan kaçınır:
for file in **/*cpp; do
grep -qm 1 Foo "$file" &&
(grep -A 3 Foo "$file" | grep -q Bar || echo "$file");
done