Cara yang baik
Biasanya Anda tidak dapat melakukan ini dengan grep tetapi Anda dapat menggunakan alat lain. AWK sudah disebutkan tetapi Anda juga dapat menggunakan sed
, seperti ini:
sed -e '1p' -e '/youpattern/!d'
Bagaimana itu bekerja:
Utilitas sed bekerja pada setiap baris secara individual, menjalankan perintah yang ditentukan pada masing-masing baris Anda dapat memiliki banyak perintah, menentukan beberapa -e
opsi. Kami dapat menambahkan setiap perintah dengan parameter rentang yang menentukan apakah perintah ini harus diterapkan ke baris tertentu atau tidak.
"1p" adalah perintah pertama. Ini menggunakan p
perintah yang biasanya mencetak semua baris. Tapi kami menambahkannya dengan nilai numerik yang menentukan rentang yang harus diterapkan. Di sini, kami menggunakan 1
yang berarti baris pertama. Jika Anda ingin mencetak lebih banyak baris, Anda dapat menggunakan di x,yp
mana x
baris pertama untuk dicetak, y
adalah baris terakhir untuk mencetak. Misalnya untuk mencetak 3 baris pertama, Anda akan menggunakan1,3p
Perintah selanjutnya adalah d
yang biasanya menghapus semua baris dari buffer. Sebelum perintah ini kita menempatkan yourpattern
antara dua /
karakter. Ini adalah cara lain (pertama adalah untuk menentukan baris mana seperti yang kita lakukan dengan p
perintah) dari pengalamatan baris yang harus dijalankan oleh perintah. Ini berarti perintah hanya akan bekerja untuk garis yang cocok yourpattern
. Kecuali, kita menggunakan !
karakter sebelum d
perintah yang membalikkan logikanya. Jadi sekarang akan menghapus semua garis yang tidak cocok dengan pola yang ditentukan.
Pada akhirnya, sed akan mencetak semua garis yang tersisa di buffer. Tapi kami menghapus garis yang tidak cocok dari buffer sehingga hanya garis yang cocok yang akan dicetak.
Singkatnya: kami mencetak baris ke-1, lalu kami menghapus semua baris yang tidak cocok dengan pola kami dari input. Sisa baris dicetak (sehingga hanya baris yang melakukan sesuai pola).
Masalah lini pertama
Seperti yang disebutkan dalam komentar, ada masalah dengan pendekatan ini. Jika pola yang ditentukan cocok dengan baris pertama, maka akan dicetak dua kali (sekali dengan p
perintah dan sekali karena kecocokan). Kita dapat menghindari ini dengan dua cara:
Menambahkan 1d
perintah setelah 1p
. Seperti yang telah saya sebutkan, d
perintah menghapus baris dari buffer dan kami menentukan rentangnya dengan nomor 1, yang berarti hanya akan menghapus baris ke-1. Jadi perintahnya adalahsed -e '1p' -e '1d' -e '/youpattern/!d'
Menggunakan 1b
perintah, alih-alih 1p
. Itu tipuan. b
perintah memungkinkan kita untuk beralih ke perintah lain yang ditentukan oleh label (dengan cara ini beberapa perintah dapat dihilangkan). Tetapi jika label ini tidak ditentukan (seperti dalam contoh kita) itu hanya melompat ke akhir perintah, mengabaikan sisa perintah untuk baris kita. Jadi dalam kasus kami, d
perintah terakhir tidak akan menghapus baris ini dari buffer.
Contoh lengkap:
ps aux | sed -e '1b' -e '/syslog/!d'
Menggunakan titik koma
Beberapa sed
implementasi dapat menghemat Anda mengetik dengan menggunakan titik koma untuk memisahkan perintah daripada menggunakan beberapa -e
opsi. Jadi jika Anda tidak peduli tentang menjadi portabel perintahnya akan ps aux | sed '1b;/syslog/!d'
. Ini berfungsi setidaknya dalam GNU sed
dan busybox
implementasi.
Cara yang gila
Namun, inilah cara yang agak gila untuk melakukan ini dengan grep. Jelas tidak optimal, saya memposting ini hanya untuk tujuan belajar, tetapi Anda dapat menggunakannya misalnya, jika Anda tidak memiliki alat lain di sistem Anda:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Bagaimana itu bekerja
Pertama, kami menggunakan -n
opsi untuk menambahkan nomor baris sebelum setiap baris. Kami ingin menghitung semua baris yang kami cocokkan .*
- apa pun, bahkan baris kosong. Seperti yang disarankan dalam komentar, kami juga dapat mencocokkan '^', hasilnya sama.
Kemudian kami menggunakan ekspresi reguler yang diperluas sehingga kami dapat menggunakan \|
karakter khusus yang berfungsi sebagai OR. Jadi kami cocok jika garis dimulai dengan 1:
(baris pertama) atau berisi pola kami (dalam hal ini adalah syslog
).
Masalah nomor baris
Sekarang masalahnya adalah, kita mendapatkan nomor garis jelek ini di output kita. Jika ini merupakan masalah, kami dapat menghapusnya dengan cut
, seperti ini:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
opsi menentukan pembatas, -f
menentukan bidang (atau kolom) yang ingin kita cetak. Jadi kami ingin memotong setiap baris pada setiap :
karakter dan hanya mencetak 2 dan semua kolom berikutnya. Ini secara efektif menghapus kolom pertama dengan pembatasnya dan inilah yang kita butuhkan.
ack
sangat berguna, dan mengapaperl
meroket masa lalused
,awk
dll dalam popularitas: penting untuk bagian-bagian untuk meringkas menjadi satu kesatuan yang koheren.