i want to find a sequence numbers in a file(bash script),if anyone can give me a tip. I have a file with ip address
like. 172.15.0.1 172.15.0.6 172.15.0.7 172.15.0.8 172.15.0.10 172.15.0.15 172.15.0.16
And i want to find lets say the 3 first sequence numbers
like this 172.15.0.6 172.15.0.7 172.15.0.8
i tried with grep or sed or awk or loops but i couldn't find the results i want.
CodePudding user response:
Would you please try the bash script:
#!/bin/bash
report() {
local seg=${1%.*}
for (( i = $2 - 2; i <= $2; i )); do
echo "$seg.$i"
done
}
prev=255 # initial value as a workaround
while IFS= read -r ip; do
n=${ip##*.} # extract the last octet
if (( n == prev 1 )); then
(( count ))
if (( count >= 2 )); then # found three sequences
report "$ip" "$n" # then report them
fi
else
count=0 # reset the count if fail
fi
prev=$n
done < <(tr -s ' ' '\n' < input_file.txt | sort -t. -nk4,4)
where input_file.txt
is the filename which contain the ip addresses.
Output with the provided file:
172.15.0.6
172.15.0.7
172.15.0.8
tr -s ' ' '\n'
replaces the whitespaces with newline characters so the output can be fed tosort
command.sort -t. -nk4,4
sorts the input with the last octet in numerical order.- The output is fed to the
while
loop via the process substitution< <(commands)
. - Now the
while
loop process the input line by line (ip by ip). - The variable
n
is assigned to the last (4th) octet. n
is compared with theprev
which holds the number in the last line. Ifn == prev 1
holds, the numbers are in sequence. Thencount
is accumulated.- If
count
reaches 2, the three lines including the current line are in the sequence. Then parameters are passed to the functionreport
.
CodePudding user response:
Given a file with a range of ip addresses separated by whitespace this awk solution might be what you're looking for:
$ awk -vRS=" " '/172.15.0.[6-8]/{print}' file.txt
172.15.0.6
172.15.0.7
172.15.0.8
The -vRS
part means that the RS (record separator) variable is set to one whitespace character.
CodePudding user response:
This should give:
echo "172.15.0.1 172.15.0.6 172.15.0.7 172.15.0.8 172.15.0.10 172.15.0.15 172.15.0.16" | grep -oP $(echo 172.15.0.{6..8} | tr ' ' '|')
172.15.0.6
172.15.0.7
172.15.0.8
EDIT2:
Here's my second attempt:
j=0
i=2
myip=172.15.0
allIPs="$myip.1 $myip.2 $myip.6 $myip.7 $myip.8 $myip.10 $myip.15 $myip.16"
# while less or equal than 255
while [ $i -le 255 ] ; do
# we will build a string that has a sequence range, for example 172.15.0.38|172.15.0.39|172.15.0.40
ips=""
# this builds the ip range sequence and adds it to ips
for ip in $(seq $j $i); do ips=${ips}$(echo -n 172.15.0."$ip")"|"; done
# we remove the last character which is '|'
ips=${ips::-1}
# this is the result that will match the sequence range
res=$(echo $allIPs | grep -oP $ips)
# if it matches, it will print it by checking that the IPs are actually found
if [ $(echo $res | tr ' ' '\n' | wc -l) == 3 ]; then
echo $res
fi
# to next range
j=$i
i=$(( $i 2 ))
done
# this is for the last sequence which is 253, 254, 255
res=$(echo $allIPs | grep -oP "$myip.253|$myip.254|$myip.255")
if [ $(echo $res | tr ' ' '\n' | wc -l) == 3 ]; then echo $res; fi
should give
172.15.0.6 172.15.0.7 172.15.0.8