Bisakah GNU Grep menghasilkan grup yang dipilih?

47

Apakah mungkin untuk menggunakan GNU grep untuk mendapatkan grup yang cocok dari ekspresi?

Contoh:

echo "foo 'bar'" | grep -oE "'([^']+)'"

Yang akan menghasilkan "'bar'". Tetapi saya hanya ingin mendapatkan "bar", tanpa harus mengirimkannya melalui grep sekali lagi (mis. Dapatkan grup yang cocok). Apakah itu mungkin?

Torandi
sumber

Jawaban:

50

Anda bisa menggunakannya seduntuk ini. Pada BSD sed:

echo "foo 'bar'" | sed -E "s/.*'([^']+)'.*/\\1/"

Atau, tanpa -Eopsi:

sed "s/.*'\([^']\+\)'.*/\1/"

Ini tidak berfungsi untuk input multiline. Untuk itu Anda perlu:

sed -n "s/.*'\([^']\+\)'.*/\1/p"
jtbandes
sumber
Terima kasih, sudah lupa tentang sed. Tetapi untuk memperjelas, sed tidak mengambil argumen -E ..
Torandi
Hm, itu ada di mesin saya (Mac OS X). Setelah diperiksa lebih lanjut, di halaman manual: "Opsi -E, -a dan -i adalah ekstensi FreeBSD yang tidak standar dan mungkin tidak tersedia pada sistem operasi lain."
jtbandes
1
-r sepertinya itu untukku.
Torandi
1
@jtbandes: Anda tidak memerlukan fitur tambahan untuk ekspresi ini .. Saya hanya membutuhkan 3 karakter untuk ( ) +digunakan \( \) \+: Ini sama saja:sed "s/.*'\([^']\+\)'.*/\1/"
Peter.O
2
Ini tidak berfungsi untuk input multiline. Untuk itu Anda perlu: sed -n "s/.*'\([^']\+\)'.*/\1/p"
phreakhead
28

Meskipun grep tidak dapat menampilkan grup tertentu, Anda dapat menggunakan lookahead dan di belakang pernyataan untuk mencapai apa yang Anda inginkan:

echo "foo 'bar'" | grep -Po "(?<=')[^']+(?=')"

Aldrik
sumber
8
grep -Ptidak tersedia di semua platform. Tetapi jika ya, menggunakan lookahead / belakang adalah cara yang sangat bagus untuk menyelesaikan masalah.
Sébastien
1
Apakah grep cerdas dengan pernyataan melihat ke belakang? Bagaimana kinerjanya dengan tampilan panjang? Apakah ini mengintegrasikan tampilan-belakang ke dalam semacam "pohon akhiran" dengan sisa regex?
Ross Rogers
3

Anda dapat menggunakan \Kuntuk mengatur ulang dan membuang teks pertandingan tangan kiri bersama dengan lookahead yang tidak ditambahkan ke teks pertandingan:

$ echo "foo 'bar'" | grep -oP "'\K[^']+(?=')"
bar

Hanya GNU grep.

drewk
sumber