Saya memiliki file yang berisi baris sebagai
proto=tcp/http sent=144 rcvd=52 spkt=3
proto=tcp/https sent=145 rcvd=52 spkt=3
proto=udp/dns sent=144 rcvd=52 spkt=3
Saya perlu untuk mengambil nilai proto yang tcp/http
, tcp/https
, udp/dns
.
Sejauh ini saya sudah mencoba ini grep -o 'proto=[^/]*/'
tetapi hanya mampu mengekstraksi nilai sebagai proto=tcp/
.
sed
,awk
atauperl
, tidakgrep
.Jawaban:
Dengan asumsi ini terkait dengan pertanyaan Anda sebelumnya , Anda salah jalan. Daripada mencoba untuk mengumpulkan potongan-potongan skrip yang agak / akan melakukan apa yang paling Anda inginkan sepanjang waktu dan perlu untuk mendapatkan skrip yang sama sekali berbeda setiap kali Anda perlu melakukan apa pun yang sedikit berbeda, buat saja 1 skrip yang dapat menguraikan Anda masukan file ke dalam array (di
f[]
bawah) yang memetakan nama bidang Anda (tag) ke nilai-nilai mereka dan kemudian Anda bisa melakukan apa pun yang Anda inginkan dengan hasilnya, misalnya memberikan file input ini dari pertanyaan Anda sebelumnya:kita bisa menulis skrip awk yang membuat array nilai yang diindeks dengan nama / tag mereka:
dan mengingat bahwa Anda dapat melakukan apa pun yang Anda suka dengan data Anda, rujuk saja dengan nama bidang, mis. menggunakan GNU awk
-e
untuk memudahkan pencampuran skrip dalam file dengan skrip baris perintah:sumber
perl
mungkin lebih mudah digunakan.awk
dansed
skrip biasanya lebih sederhanaperl
karena pada dasarnya merupakan superset dari mereka, dengan fitur tambahan untuk tugas-tugas umum.s/old/new/g
dan sed tidak awk jadi mari kita kesampingkan itu. Saya sama sekali tidak setuju bahwa skrip awk yang kompleks lebih mudah di perl. Mereka bisa lebih singkat tentu saja tetapi singkatnya bukan atribut yang diinginkan dari perangkat lunak, keringkasannya, dan sangat jarang bagi mereka untuk mendapatkan manfaat nyata ditambah mereka biasanya jauh lebih sulit untuk membaca itulah sebabnya orang memposting hal-hal seperti zoitz.com / archives / 13 tentang perl dan menyebutnya sebagai bahasa tulis saja, tidak seperti awk. Saya masih ingin melihat perl yang setara dengan iniDengan
grep -o
, Anda harus mencocokkan apa yang ingin Anda ekstrak. Karena Anda tidak ingin mengekstraksiproto=
string, Anda tidak harus mencocokkannya.Ekspresi reguler yang diperluas yang akan cocok dengan
tcp
atauudp
diikuti oleh garis miring dan beberapa string alfanumerik yang tidak kosong adalahMenerapkan ini pada data Anda:
Untuk memastikan bahwa kami hanya melakukan ini pada baris yang dimulai dengan string
proto=
:Dengan
sed
, menghapus semuanya sebelum karakter pertama=
dan sesudah karakter kosong pertama:Untuk memastikan bahwa kami hanya melakukan ini pada baris yang dimulai dengan string
proto=
, Anda bisa memasukkan langkah pra-pemrosesan yang sama dengangrep
seperti di atas, atau Anda bisa menggunakanDi sini, kami menekan output default dengan
-n
opsi, dan kemudian kami memicu penggantian dan cetak eksplisit baris hanya jika baris cocok^proto=
.Dengan
awk
, menggunakan pemisah bidang default, dan kemudian membelah bidang pertama=
dan mencetak bit kedua:Untuk memastikan bahwa kami hanya melakukan ini pada baris yang dimulai dengan string
proto=
, Anda bisa memasukkan langkah pra-pemrosesan yang sama dengangrep
seperti di atas, atau Anda bisa menggunakansumber
Jika Anda menggunakan GNU grep (untuk
-P
opsi), Anda dapat menggunakan:Di sini kita mencocokkan
proto=
string, untuk memastikan bahwa kita mengekstrak kolom yang benar, tetapi kemudian kita membuangnya dari output dengan\K
bendera.Di atas mengasumsikan bahwa kolom dipisahkan oleh ruang. Jika tab juga merupakan pemisah yang valid, Anda akan menggunakan
\S
untuk mencocokkan karakter non-spasi, jadi perintahnya adalah:Jika Anda juga ingin melindungi terhadap bidang yang cocok
proto=
dengan substring, seperti athisisnotaproto=tcp/https
, Anda dapat menambahkan batas kata dengan\b
seperti:sumber
grep -oP 'proto=\K\S+'
. Theproto=tcp/http
dapat diikuti oleh tab bukannya ruang, dan\S
tidak seperti[^ ]
akan ditemukan karakter non-ruang.-o
ini adalah GNUisme juga.-P
hanya didukung oleh GNUgrep
jika dibangun dengan dukungan PCRE (opsional saat membangun).Menggunakan
awk
:$1 ~ "proto"
akan memastikan kami hanya mengambil tindakan sesuai dengan yang adaproto
di kolom pertamasub(/proto=/, "")
akan menghapusproto=
dari inputprint $1
mencetak kolom yang tersisasumber
Kode golf pada
grep
solusinyaatau bahkan
sumber
Menggunakan
cut
perintah:sumber
http
dandns
.Hanya
grep
solusi lain :Dan yang serupa dengan
sed
mencetak hanya grup yang ditangkap yang cocok:sumber
awk
Pendekatan lain :Itu akan mengatur pemisah bidang awk ke salah satu
=
atau spasi. Kemudian, jika garis cocok dengan a=
, maka salah satuud
atautc
diikuti olehp
, cetak bidang ke-2.sed
Pendekatan lain (tidak portabel untuk semua versised
, tetapi bekerja dengan GNUsed
):The
-n
berarti "tidak mencetak" dan-E
memungkinkan diperpanjang ekspresi reguler yang memberi kita\S
untuk "non-spasi",+
untuk "satu atau lebih" dan tanda kurung untuk menangkap. Akhirnya,/p
pada akhirnya akan membuat sed garis cetak hanya jika operasi berhasil jadi jika ada kecocokan untuk operator substitusi.Dan, satu perl:
The
-n
berarti "membaca file baris demi baris masukan dan menerapkan script yang diberikan oleh-e
masing-masing baris". The-l
menambahkan baris baru untuk setiapprint
panggilan (dan menghapus keluar baris dari input). Script itu sendiri akan mencetak bentangan karakter non-spasi terpanjang yang ditemukan setelah aproto=
.sumber
-E
semakin portabel, tetapi\S
tidak.[^[:space:]]
adalah setara yang lebih portabel.Berikut ini solusi lain yang cukup mudah:
sumber
grep
tidak cocok dengan apa pun.[tc,ud]\*\\/.*
mencari satu kemunculan baikt
, atauc
,,
atauu
ataud
, diikuti oleh*
karakter literal , kemudian ap
dan garis miring terbalik. Anda mungkin bermaksudgrep -Eo '(tc|ud)p/.* ' file | awk '{print $1}'
. Tapi kemudian, jika Anda menggunakan awk, Anda mungkin juga melakukan semuanya dalam awk:awk -F'[= ]' '/(tc|ud)p/{print $2}' file
.[tc,ud]p
berarti "salaht
,c
,,
,u
ataud
diikuti olehp
. Jadi cocok di sini hanya karenatcp
memilikicp
danudp
memilikidp
. Tapi itu juga akan cocok,p
atautp
dll Juga, sekarang bahwa Anda memiliki*
, maka akan cocokppp
juga (*
berarti "0 atau lebih" sehingga akan cocok bahkan ketika tidak cocok). Anda tidak ingin kelas karakter ([ ]
), yang Anda inginkan adalah grup:(tc|ud)
(gunakan dengan-E
benderagrep
). Juga,.*
membuatnya cocokkan seluruh baris\*
untuk mendapatkan yang pertama*
dalam perintah mereka untuk tampil sebagai * dan bukan sebagai markdown miring. Ketika Anda menempatkan perintah ke dalam format kode, Anda menyebabkan\
sebelum*
muncul (sehingga menyebabkan perintah gagal). Saat Anda mengedit posting orang lain, harap diperhatikan untuk mengubah tampilan posting seperti ini.ppp
. Tentu saja Anda benar bahwa itu akan cocok,p
atautp
- atauuucp
,ttp
,cutp
,ductp
ataud,up
.sumber
opsi memotong:
-f
- bidang-d
- delimetersumber