"Foo" içeren satırlar için nasıl dizin oluşturabilirim, ancak yalnızca bir sonraki satır "Bar" ı içerdiğinde eşleşmeleri nasıl alabilirim?
"Foo" içeren satırlar için nasıl dizin oluşturabilirim, ancak yalnızca bir sonraki satır "Bar" ı içerdiğinde eşleşmeleri nasıl alabilirim?
Yanıtlar:
@ warl0ck bana doğru yönde işaret etti pcregrep
, ama dedim "içerir", "değil" ve bir dizin değil, bir dosya hakkında sordum.
Bu benim için işe yarıyor gibi görünüyor.
pcregrep -rMi 'Foo(.*)\n(.*)Bar' .
Grep'in kendisi desteklemiyor gibi görünüyor, bunun yerine pcregrep kullanın:
Foo
Bar
Foo
abc
pcregrep -M "Foo\nBar" file
Var:
Foo
Bar
Foo
ve Bar
tüm çizgiyi içerecekti.
Bir sed
senaryo ile:
#!/bin/sed -nf
/^Foo/{
h # put the matching line in the hold buffer
n # going to nextline
/^Bar/{ # matching pattern in newline
H # add the line to the hold buffer
x # return the entire paragraph into the pattern space
p # print the pattern space
q # quit the script now
}
}
Kullanmak için:
chmod +x script.sed
printf '%s\n' * | ./script.sed
printf
Burada bir satırda her biri üzerinde geçerli dizindeki tüm dosyaları görüntülemek ve onu geçmek sed
.
Not : bu alfabetik sıraya göre sıralanmıştır.
Yararlı pattern space
ve hold space
BURAYA daha fazla bilgi .
grymoire.comshell
programlama hakkında gerçekten iyi şeyler var .
h, n, H, x, p, q
geliyor? Çok ilginç.
pattern space
& hold space
: Grymoire.com/Unix/Sed.html#uh-56 veya Fransızca yorumda
grep
Yalnızca kullanarak , aşağıdaki boruyu oluşturabilirsiniz:
grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'
Birincisi grep
, içerdiği tüm çizgileri Foo
ve maçtan sonraki çizgiyi alacak. Sonra Bar
maçtan önce olduğu kadar satır içeren satırlar alırız ve son olarak bu çıktıdaki satırları çıkarırız Foo
.
DÜZENLEME: As manatwork işaret, gözleme konusunda bazı sorunlu durumlar vardır. Her ne kadar ilginç bir zorluk olsa da, grep
'line odaklı işlevsellik nedeniyle , bununla ilgili herhangi bir çözümün bir' hack 'olması muhtemeldir ve muhtemelen pcregrep
eldeki göreve daha uygun bir şey kullanmaktan daha iyidir .
find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
Nathan'ın çözümünü kullanmayı tercih ederken pcregrep
, burada sadece grep kullanan çözüm
grep -o -z -P 'Foo(.*)\n(.*)Bar' file
Seçenekler açıklaması:
-o
yalnızca eşleşen kısmı yazdırın. Eklenmesi -z
tüm dosyanın çıktısını alacaktır (bir yerde \ 0 olmadığı sürece)-z
Girdiyi, her biri yeni satır yerine sıfır bayt (ASCII NUL karakteri) ile sonlandırılmış bir dizi satır olarak kabul edin.-P
perl normal ifade sözdizimi EDIT: Bu sürüm eşleşen tüm satırları yazdırır
grep -o -P -z '(.*)Foo(.*)\n(.*)Bar(.*)' file
-z
. Tüm ifadeden önce ve sonra bazı “(. *)”, Eşleşen tüm satırların çıktısını almasını sağlar. Şimdilik “Foo” öncesi ve “Bar” sonrası alt dizeler görüntülenmiyor.
Awk ile:
awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
/foo/ {prev=$0; next}
{prev=""}' file1...
(awk sınırlaması hakkında genel not: bazı dosya adları "=" karakter içeriyorsa, awk ./filename
yerine bunları filename
iletmeniz gerektiğini unutmayın)