mengambil substring dari hasil grep

4

Diberikan file log, saya biasanya akan melakukan sesuatu seperti ini:

grep 'marker-1234' filter_log

Apa perbedaan menggunakan '' atau "" atau tidak sama sekali dalam polanya?

Perintah grep di atas akan menghasilkan ribuan baris; apa yang saya inginkan. Di dalam baris-baris itu, Biasanya ada satu potong data yang saya cari. Terkadang, saya menggunakan awk untuk mencetak bidang yang saya cari. Dalam hal ini, format log berubah, saya tidak bisa bergantung pada posisi secara eksklusif, belum lagi, data log aktual dapat mendorong posisi ke depan.

Untuk membuat hal ini dapat dimengerti, katakanlah baris log berisi alamat IP, dan hanya itu yang saya cari, jadi saya nanti dapat memipkannya untuk mengurutkan dan unik dan mendapatkan beberapa hitungan penghitungan.

Contohnya mungkin:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: [email protected] to [email protected] [stat-xyz9876]

Perintah grep pertama akan memberi saya ribuan baris seperti di atas, dari sana, saya ingin menyalurkannya ke sesuatu, mungkin sed, yang dapat menarik pola di dalam, dan hanya mencetak pola.

Untuk contoh ini, cukup menggunakan alamat IP. Saya mencoba. Aku s sed tidak dapat mengerti [0-9] {1,3}. sebagai sebuah pola? Saya harus [0-9] [0-9] [0-9]. yang menghasilkan hasil aneh sampai seluruh pola dibuat.

Ini tidak spesifik untuk alamat IP, polanya akan berubah, tapi saya bisa menggunakannya sebagai templat pembelajaran.

Terima kasih semua.

user17245
sumber
Ini kedengarannya sangat terkait pemrograman, bahkan perintah bash sederhana pun seperti grep dan awk menurut saya lebih baik dijawab di stackoverflow.
Josh K
@Josh: SU memiliki banyak prajurit commandline linux yang dapat menangani pertanyaan semacam ini, dan diterima di sini. itu mungkin salah satu dari pertanyaan-pertanyaan yang cocok di kedua situs, jadi itu benar-benar terserah kepada penanya.
quack quixote
Saya memikirkannya, dan jujur ​​saja, saya tidak tahu harus memposting di mana. Aku pergi dengan nama situs, mencari SO lebih umum, dan SU lebih banyak jenis admin. Saya menemukan skrip shell paling cepat terkait admin. Tentu, Anda masuk ke proyek-proyek eksklusif tcl atau bash besar karena satu dan lain alasan, dalam hal ini saya akan mempersempitnya untuk pemrograman terkait dan posting ke SO. Ini lebih dari satu kapal, dan SU sepertinya rumah yang bagus. Maaf jika saya memposting di tempat yang salah, tetapi tampaknya daerah abu-abu dalam beberapa kasus.
user17245
@ allentown: sebenarnya Server Fault adalah lebih banyak jenis admin; Pengguna Super adalah lebih banyak hal pengguna akhir. (tetapi pengguna akhir pengguna daya.) Bagaimanapun, pertanyaan ini mungkin diterima pada SO / SF / SU. Anda sudah menerima jawaban, jadi jika Anda puas Anda dapat menyebutnya selesai. atau jika Anda ingin kami dapat memigrasikannya ke SO / SF; cukup beri tanda untuk perhatian moderator dan beri tahu kami ke mana harus mengirimnya. Terima kasih!
quack quixote
@ quack: Tidak apa-apa, saya hanya berpikir bahwa jawaban yang lebih baik mungkin ditemukan di sana, namun sepertinya sudah ditemukan.
Josh K

Jawaban:

7

Saya tidak tahu OS apa yang Anda gunakan, tetapi pada FreeBSD 7.0+ grep memiliki -o pilihan untuk mengembalikan hanya bagian yang cocok dengan pola. Jadi kamu bisa
grep "marker-1234" filter_log | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

Mengembalikan daftar alamat IP yang adil dari 'filter_log "...

Ini berfungsi pada sistem saya, tetapi sekali lagi, saya tidak tahu apa yang didukung versi grep Anda.

Chris S
sumber
Saya pikir semua jawaban di sini adalah cara terbaik untuk belajar dan mendekati hasil akhir dengan jawaban yang sama. Saya sangat suka yang ini karena mudah diingat dan hanya chaining beberapa perintah grep. Pada Mac OS X, saya sepertinya memiliki opsi -o, dan tentu saja menggunakan opsi -E sudah cukup sering. Terimakasih atas balasan anda
user17245
3

Anda dapat melakukan semua ini hanya dalam satu awk perintah. Tidak perlu menggunakan alat lain

$ awk '/marker-1234/{for(o=1;o<=NF;o++){if($o~/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)print $o }  }' file
(123.123.123.123)
user31894
sumber
Terima kasih, itu berhasil, awk dapat melukai kepala Anda sedikit di kali, tapi saya terbiasa dengan FOO .... satu aspek liner dari hal-hal cepat di shell. Sangat kuat.
user17245
2

Anda dapat mempersingkat yang kedua grep sedikit seperti ini:

grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'

Untuk menjawab pertanyaan pertama Anda, tanda kutip ganda memungkinkan shell untuk melakukan berbagai hal seperti ekspansi variabel, tetapi melindungi beberapa karakter meta dari kebutuhan untuk melarikan diri. Kutipan tunggal mencegah shell melakukan ekspansi tersebut. Tidak menggunakan tanda kutip membuat semuanya terbuka lebar.

$ empty=""
$ text1="some words"
$ grep $empty some_file
(It seems to hang, but it's just waiting for input since it thinks "some_file" is 
the pattern and no filename was entered, so it thinks input is supposed to come
from standard input. Press Ctrl-d to end it.)
$ grep "$empty" some_file
(The whole file is shown since a null pattern matches everything.)
$ grep $text1 some_file
grep: words: No such file or directory
some_file:something
some_file:some words
(It sees the contents of the variable as two words, the first is seen as the 
pattern, the second as one file and the filename as a second file.)
$ grep "$text1" some_file
some_file:some words
(Expected results.)
$ grep '$text1' some_file
(No results. The variable isn't expanded and the file doesn't contain a
string that consists of literally those characters (a dollar sign followed
by "text1"))

Anda dapat mempelajari lebih lanjut di bagian "QUOTING" di man bash

Dennis Williamson
sumber
Tulisan bagus, terima kasih. Saya perlu mendapatkan penanganan yang lebih baik tentang ini dengan regad ke IFS juga, saya cukup menutup telepon itu beberapa hari yang lalu, tetapi berhasil membuat IFS bermain bagus. Ini adalah hal yang mengerikan ketika Anda memiliki IFS diatur dan lupa tentang hal itu, heran jika sedang berlangsung selama satu jam.
user17245
Itu ide yang baik untuk menjadi kebiasaan untuk selalu menyimpan nilai IFS dan pulihkan sesegera mungkin: saveIFS="$IFS"; IFS=","; do_something; IFS="$saveIFS"; do_other_stuff
Dennis Williamson
+1 Panggilan bagus di regex, saya tidak banyak menggunakannya, jadi saya cenderung sedikit tidak efisien.
Chris S
1

Lihatlah xargs perintah. Anda harus dapat melakukan sesuatu seperti:

grep 'marker-1234' filter_log | xargs grep "(" | cut -c1-15

Ini mungkin bukan tepatnya, tetapi xargs adalah perintah yang ingin Anda gunakan

Jennifer
sumber