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?
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?
Jawaban:
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.
Mungkin yang paling mudah adalah,
sed -n '/pattern/{=; q;}' file
Terima kasih @ JoshepR untuk menunjukkan kesalahan
dc
, saya sendiri, mungkin.
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 wc
dan 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))
}
sed
hanya mencetak nomor baris yang cocok dan terakhir, kemudian tr
menerjemahkan \n
ewlines yang akan diintervensi, dan read
membaca hasil pertama sed
ke dalam $ml
dan semua yang lain ke dalam $ll
. Beberapa kasus pencocokan mungkin ditangani dengan melepaskan semua kecuali hasil terakhir dari $ll
ekspansi 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:
"$IP"
kemudian \n
ewlinetr
- yang menerjemahkan nol ke \n
ewlines lalu ke~/file
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"
$.
konter?
$after
untuk $. - $before
.
$. - 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.
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
Grep
memiliki fitur yang dapat menghitung berapa kali pola tertentu ditemukan. Jika Anda menggunakan -c
perintah yang akan melakukannya. Dengan -c
dan -v
perintah, 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.