У мене довгий список IP-адрес, які не є послідовними. Мені потрібно знайти, скільки IP-адрес є до / після певної IP-адреси. Як я можу цього досягти?
У мене довгий список IP-адрес, які не є послідовними. Мені потрібно знайти, скільки IP-адрес є до / після певної IP-адреси. Як я можу цього досягти?
Відповіді:
Можливо, найпростіше,
sed -n '/pattern/{=; q;}' file
Дякуємо @JoshepR за вказівку на помилку
dc, мабуть, передавав би це безпосередньо безпосередньо собі.
Я зробив це двома способами, хоча думаю, що мені це найбільше подобається:
: $(( 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
Це зберігає всі ці як поточні змінні оболонки - і потім оцінює їх у циклі for для виведення. Він підраховує загальний рядок у файлі з wcі отримує номер першого рядка, що відповідає sed.
Його вихід:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Я також робив:
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друкує лише відповідні та останні рядкові номери, а потім trпереводить втручаються \newlines до, і readчитає результати перших sedрезультатів $mlі всі інші $ll. Можливі випадки декількох матчів обробляються шляхом зняття всіх, крім останнього результату, з $llрозширення, коли його знову встановлюють пізніше.
Його вихід:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Обидва методи були протестовані на файлі, сформованому таким чином:
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
Це відбувається за номером рядка:
"$IP"потім електронну \nлініюtr- що переводить нулі в \newlines потім у~/fileОсь трохи коду Perl, який це робить:
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
При цьому підраховується загальна кількість рядків до і після рядка, що містить IP 192.168.1.1. Замініть потрібний IP.
Не використовуючи нічого, крім 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"
$.замість лічильника?
$afterдля $. - $before.
$. - 1, зберігати $.в $tmp. Кінцевий друк $. - $tmp. Тому нам не потрібен лічильник як до, так і після. Звичайно, це менш читається, ніж ваше.
Я пробував такі команди, які трохи складні, але давали б точні результати:
Після:
a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l
Перед:
echo "`cat -n file | grep <Pattern> | awk '{print $1}'`-1" | bc -l
Grepмає функцію, яка може підраховувати кількість разів знайденого певного шаблону. Якщо ви використовуєте -cкоманду, яка це зробить. З -cі -vкомандами, це буде підрахувати , скільки разів це не відповідає певним шаблоном
Приклад:
grep -c -v <pattern> file
Тож якщо ви спробуєте щось на кшталт:
grep -c -v 192.168.x.x file.log це повинно працювати.