Hitung jumlah total garis sebelum / setelah kecocokan pola


9

Saya memiliki daftar panjang alamat IP, yang tidak berurutan. Saya perlu menemukan berapa banyak alamat IP yang ada sebelum / sesudah alamat IP tertentu. Bagaimana saya bisa mencapai ini?


Apakah Anda memiliki duplikat IP?
— cuonglm

Tidak. Semua alamat IP unik.
— Mandar Shinde

Apa arti sebelum / sesudah untuk alamat IP? Secara khusus, apakah Anda memiliki alamat IPv4 dan IPv6? Bagaimana mereka membandingkan?
— vinc17

Apakah Anda perlu file diurutkan?
— cuonglm

2
@ vinc17 - File hanya berisi alamat IP (IPv4), tidak ada data lain yang disertakan. Jika ada 1000 alamat IP secara total, dan kecocokan ditemukan di lokasi ke-300, berarti ada 299 baris sebelum pertandingan dan 700 baris setelah pertandingan.
— Mandar Shinde

Jawaban:


8

Jumlah baris sebelum dan sesudah pertandingan, termasuk pertandingan (yaitu Anda harus mengurangi 1 dari hasil jika Anda ingin mengecualikan pertandingan):

sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l

Tetapi ini tidak ada hubungannya dengan alamat IP pada khususnya.


4

Mungkin yang paling mudah adalah,

sed -n '/pattern/{=; q;}' file

Terima kasih @ JoshepR untuk menunjukkan kesalahan


Ini hanya mencetak nomor baris di mana pola terjadi.
— Joseph R.

@ JosephRR. - tidak, itu mencetak setiap nomor baris di mana setiap pertandingan terjadi.
— mikeserv

@ mikeserv Saya tahu tetapi OP menetapkan bahwa alamat IP unik. OP juga tidak ingin nomor baris tempat pertandingan terjadi; mereka menginginkan jumlah garis sebelum pola terjadi dan jumlah garis setelahnya.
— Joseph R.

@ JosephephR - cara tercepat untuk sampai pada penghitungan itu adalah dengan menghitung angka-angka garis - Saya hanya akan menyalurkan ini langsung ke dc, saya sendiri, mungkin.
— mikeserv

@ mikeserv Saya tidak berpendapat bahwa informasi dari jawaban ini tidak berguna, saya hanya mengatakan bahwa kode ini sendiri tidak melakukan apa yang diinginkan OP.
— Joseph R.

3

Saya melakukan dua cara ini, meskipun saya pikir saya paling suka ini:

: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
  $(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do  printf '%s line%s :\t%d\n' \
        "${n%s}" "${n##*[!s]}" $((${n%s}l))
done

Itu menyimpan semua itu sebagai variabel shell saat ini - dan mengevaluasi mereka dalam for for loop kemudian untuk output. Itu menghitung total baris dalam file dengan wcdan mendapat nomor baris pertama yang cocok dengannya sed.

Keluarannya:

last line :     1000
match line :    200
after lines :   799
before lines :  199

Saya juga melakukan:

sed -n "/$IP/=;\$=" ~/file |  
tr \\n \  | { 
IFS=' ' read ml ll 
printf '%s line%s:\t%d\n' \
    last '' $((ll=${ll##* }))
    match '' $ml \
    after s "$((al=ll-ml-1)) \ 
    before s $((bl=ml-1))
}

sedhanya mencetak nomor baris yang cocok dan terakhir, kemudian trmenerjemahkan \newlines yang akan diintervensi, dan readmembaca hasil pertama sedke dalam $mldan semua yang lain ke dalam $ll. Beberapa kasus pencocokan mungkin ditangani dengan melepaskan semua kecuali hasil terakhir dari $llekspansi saat mengaturnya kembali nanti.

Keluarannya:

last line :     1000
match line :    200
after lines :   799
before lines :  199

Kedua metode diuji pada file yang dihasilkan dengan cara berikut:

IP='some string for which I seek' 
for count in 1 2 3 4 5 
do  printf '%.199d%s\n' 0 "$IP" 
done | tr 0 \\n >~/file 

Ya, dengan nomor baris:

  1. mengatur string pencarian
  2. loop lima kali untuk memastikan akan ada beberapa pertandingan
  3. mencetak 199 angka nol maka "$IP"kemudian \newline
  4. output pipa ke tr- yang menerjemahkan nol ke \newlines lalu ke~/file

2

Berikut sedikit kode Perl yang melakukannya:

perl -ne '
     if(1 .. /192\.168\.1\.1/) { $before++ }
     else                      { $after++  }
     $before--; # The matching line was counted
     END{print "Before: $before, After: $after\n"}' your_file

Ini menghitung jumlah total baris sebelum dan sesudah baris yang berisi IP 192.168.1.1. Ganti dengan IP yang Anda inginkan.

Hanya menggunakan Bash:

before=0
match=0
after=0
while read line;do
    if [ "$line" = 192.168.1.1 ];then
        match=1
    elif [ $match -eq 0 ];then
        before=$(($before+1))
    else
        after=$(($after + 1))
    fi
done < your_file
printf "Before: %d, After: %d\n" "$before" "$after"

BASH lebih disukai.
— Mandar Shinde

2
@ Joseph R .: Mengapa Anda tidak menggunakan $.konter?
— cuonglm

@ Gnouc tentu saja saya bisa. Saya hanya berpikir ini lebih mudah dibaca daripada pengaturan $afteruntuk $. - $before.
— Joseph R.

Tidak, maksud saya: jika cocok, cetak $. - 1, simpan $.ke $tmp. Cetak akhir $. - $tmp. Jadi kita tidak perlu kontra untuk sebelum dan sesudah. Tentu saja itu kurang mudah dibaca daripada milik Anda.
— cuonglm

@MandarShinde Silakan lihat hasil edit. Saya menambahkan jawaban Bash murni.
— Joseph R.

2

Saya mencoba perintah berikut, yang sedikit rumit, tetapi akan memberikan hasil yang akurat:

Setelah:

a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l

Sebelum:

echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l

2

Sebuah awksolusi melaporkan jumlah baris sebelum dan setelah pertandingan terakhir

awk '/192\.168\.1\.1/{x=NR};{y=NR} END{printf "before-%d, after-%d\n" , x-1, y-x}'  file

1

Grepmemiliki fitur yang dapat menghitung berapa kali pola tertentu ditemukan. Jika Anda menggunakan -cperintah yang akan melakukannya. Dengan -cdan -vperintah, ini akan menghitung berapa kali ini tidak cocok dengan pola tertentu

Contoh:

grep -c -v <pattern> file

Jadi, jika Anda mencoba sesuatu seperti:

grep -c -v 192.168.x.x file.log itu seharusnya bekerja.


Ini menghitung jumlah kemunculan IP target. Ini bukan yang diminta OP.
— Joseph R.

Saya baru saja mengeditnya, jika dia meminta untuk menghitung semua IP lain sebelum dan setelah IP tertentu, hasil edit harus bekerja untuknya.
— ryekayo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.