Ben sırayla olmayan IP adresleri, uzun bir liste yaşıyorum. Belirli bir IP adresinden önce / sonra kaç tane IP adresi olduğunu bulmam gerekiyor. Bunu nasıl başarabilirim?
Ben sırayla olmayan IP adresleri, uzun bir liste yaşıyorum. Belirli bir IP adresinden önce / sonra kaç tane IP adresi olduğunu bulmam gerekiyor. Bunu nasıl başarabilirim?
Yanıtlar:
Belki de en kolayı,
sed -n '/pattern/{=; q;}' file
Hatayı gösterdiğin için teşekkürler @JoshepR
dc
kendime, muhtemelen kendime bağlarım .
Bunu en çok sevdiğimi düşünmeme rağmen bunu iki şekilde yaptım
: $(( 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
Bu, tüm bunları geçerli kabuk değişkenleri olarak kaydeder ve bunları çıkış için for döngüsünde değerlendirir. Dosyadaki toplam satırları sayar ve wc
ilk eşleşen satır numarasını alır sed
.
Çıkışı:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Ben de yaptım:
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
yalnızca eşleşen ve son satır numaralarını yazdırır, ardından tr
araya giren \n
ewline'larıVe read
ilk okur sed
bireyin içine sonuçları $ml
ve içine tüm diğerleri $ll
. Olası çoklu eşleşme vakaları, $ll
daha sonra tekrar ayarlandığında, genişlemenin son sonucu dışındaki tüm sonuçların çıkarılmasıyla ele alınır .
Çıkışı:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Her iki yöntem de oluşturulan dosyada şu şekilde test edildi:
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
Satır numarasına göre yapar:
"$IP"
sonra bir \n
ewline yazdırırtr
- sıfırları \n
ewlines'a çevirir~/file
İşte bunu yapan biraz Perl kodu:
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
Bu, IP'yi içeren satırdan önceki ve sonraki toplam satır sayısını sayar 192.168.1.1
. İstediğiniz IP ile değiştirin.
Bash dışında hiçbir şey kullanmamak:
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"
$.
sayaç yerine kullanmıyorsunuz ?
$after
kadar $. - $before
.
$. - 1
kaydetme, $.
için $tmp
. Yazdırmayı bitirin $. - $tmp
. Yani hem öncesi hem de sonrası için sayaca ihtiyacımız yok. Elbette sizinkinden daha az okunabilir.
Biraz karmaşık olan ancak doğru sonuçlar verecek aşağıdaki komutları deniyordum:
Sonra:
a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l
Önce:
echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l
Grep
belirli bir desenin kaç kez bulunduğunu sayabilen bir özelliğe sahiptir. Bunu -c
yapacak komutu kullanırsanız . İle -c
ve -v
komuta, bu belli bir kalıba uymayan kaç kez sayacaktır
Misal:
grep -c -v <pattern> file
Yani şöyle bir şey denerseniz:
grep -c -v 192.168.x.x file.log
bu işe yarayacak.