Bagaimana saya bisa mendapatkan direktori untuk baris yang berisi "Foo", tetapi hanya mendapatkan kecocokan ketika baris berikutnya juga berisi "Bar"?
Bagaimana saya bisa mendapatkan direktori untuk baris yang berisi "Foo", tetapi hanya mendapatkan kecocokan ketika baris berikutnya juga berisi "Bar"?
Jawaban:
@ warl0ck menunjuk saya ke arah yang benar dengan pcregrep
, tetapi saya berkata "berisi", bukan "adalah", dan saya bertanya tentang direktori, bukan file.
Ini sepertinya bekerja untuk saya.
pcregrep -rMi 'Foo(.*)\n(.*)Bar' .
Grep sendiri sepertinya tidak mendukungnya, gunakan pcregrep sebagai gantinya:
Foo
Bar
Foo
abc
pcregrep -M "Foo\nBar" file
Punya:
Foo
Bar
Foo
dan Bar
akan terdiri dari seluruh lini.
Dengan sed
skrip:
#!/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
}
}
Untuk menggunakannya:
chmod +x script.sed
printf '%s\n' * | ./script.sed
Di printf
sini menampilkan semua file dalam direktori saat ini pada setiap baris, dan meneruskannya ke sed
.
Catatan : ini disortir berdasarkan urutan abjad.
Info lebih berguna pattern space
dan hold space
DI SINI .
grymoire.com memiliki hal-hal yang sangat baik tentang shell
pemrograman.
h, n, H, x, p, q
artinya? Sangat menarik.
pattern space
& hold space
: grymoire.com/Unix/Sed.html#uh-56 atau dalam bahasa Perancis commentcamarche.net/faq/9536-sed-introduction-a-sed-part-i
Hanya menggunakan grep
, Anda bisa membuat pipa berikut:
grep -A1 'Foo' input_file | grep -B1 'Bar' | grep 'Foo'
Yang pertama grep
akan mendapatkan semua baris yang berisi Foo
serta baris setelah pertandingan. Lalu kami mendapatkan garis yang berisi Bar
serta garis sebelum pertandingan, dan akhirnya mengekstrak garis dari output yang berisi ini Foo
.
EDIT: Seperti yang ditunjukkan oleh manatwork , ada beberapa kasus bermasalah yang harus diperhatikan. Meskipun tantangan yang menarik, karena grep
fungsionalitas yang berorientasi pada garis, solusi apa pun yang ada kemungkinan adalah 'retas' dan Anda mungkin lebih baik menggunakan sesuatu seperti pcregrep
yang lebih cocok untuk tugas yang sedang dihadapi.
find . -name '*.txt' | xargs grep -A1 'Foo' | grep -B1 'Bar'
Sementara saya lebih suka menggunakan solusi Nathan pcregrep
, berikut adalah solusi hanya menggunakan grep
grep -o -z -P 'Foo(.*)\n(.*)Bar' file
Penjelasan opsi:
-o
hanya mencetak bagian yang cocok. Diperlukan sejak dimasukkannya -z
akan mencetak seluruh file (kecuali ada \ 0 di suatu tempat)-z
Perlakukan input sebagai satu set garis, masing-masing diakhiri dengan byte nol (karakter ASCII NUL) alih-alih baris baru.-P
sintaks perl regex EDIT: Versi ini mencetak seluruh baris yang cocok
grep -o -P -z '(.*)Foo(.*)\n(.*)Bar(.*)' file
-z
. Beberapa "(. *)" Sebelum dan sesudah seluruh ekspresi akan membuatnya menampilkan seluruh baris yang cocok. Untuk saat ini substring sebelum "Foo" dan setelah "Bar" tidak ditampilkan.
Dengan awk:
awk '/bar/ && prev != "" {print FILENAME ": " prev "\n" FILENAME ": " $0}
/foo/ {prev=$0; next}
{prev=""}' file1...
(catatan umum tentang batasan awk: berhati-hatilah bahwa jika beberapa nama file mungkin berisi "=" karakter, Anda harus meneruskannya sebagai ./filename
ganti filename
awk)