Luiz
January 28, 2019, 1:25pm
1
Hi there,
An ip address consists of four decimal numbers, each ranging from 0 to 255, separated by dots.
I need to find a script in R that search for users which the last octect ip address is greater or equal than 128.
Let's say I have the following data:
library(iptools)
library(dplyr)
library(stringr)
library(tidyr)
IP_LIST <- data.frame(
"User" = c("John", "Carl", "Mary",
"Kim", "Jane", "Jessie",
"Peter"),
"IP" = c('172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10') )
The result should give me the users/ips:
User IP_Address
Carl 172.16.2.129
Mary 192.16.15.254
Jessie 192.168.25.200
Because all those ip's last octects are greater or equal than 128 (129, 254 and 200).
I appreciate any help.
Kind regards,
Luiz.
Here's one way to do it:
IP_LIST <- data.frame("User" = c("John",
"Carl",
"Mary",
"Kim",
"Jane",
"Jessie",
"Peter"),
"IP" = c('172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10'))
IP_LIST$IP <- as.character(x = IP_LIST$IP)
custom_function <- function(IP_address)
{
fourth_octet <- stringi::stri_split_fixed(str = IP_address,
pattern = ".",
simplify = TRUE)[4]
return(ifelse(test = (as.integer(x = fourth_octet) > 128),
yes = TRUE,
no = FALSE))
}
indices <- sapply(X = IP_LIST$IP,
FUN = custom_function)
IP_LIST[indices,]
#> User IP
#> 3 Mary 172.16.2.129
#> 4 Kim 198.16.15.254
#> 6 Jessie 192.168.25.200
Created on 2019-01-28 by the reprex package (v0.2.1)
library(tidyverse)
IP_LIST <- data.frame(
"User" = c("John", "Carl", "Mary",
"Kim", "Jane", "Jessie",
"Peter"),
"IP" = c('172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10'), stringsAsFactors = FALSE)
IP_LIST %>%
separate(IP, c(NA, NA, NA, "oct4"), "\\.", remove = FALSE) %>%
mutate_at("oct4", as.integer) %>%
filter(oct4 >= 128) %>%
select(-oct4)
1 Like
taras
January 28, 2019, 3:46pm
5
Conceptually, you want to:
Split your IP by .
delimiter and get the last (4th) match
Convert the result into an integer for further eval
Evaluate against a filter (>=128
)
It's a bit tricky to do in R as I'm not aware of any functions that would return exactly first or last match, but with a bit of purrr
, nothing is impossible:
library(tidyverse)
IP_LIST <- tibble(
"User" = c("John", "Carl", "Mary",
"Kim", "Jane", "Jessie",
"Peter"),
"IP" = c('172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10') )
result <- IP_LIST %>%
mutate(split = str_split(IP, "\\."),
num = as.integer(unlist(map(split, ~.[4])))) %>%
filter(num >= 128) %>%
select(-num, -split)
# A tibble: 3 x 2
User IP
<chr> <chr>
1 Mary 172.16.2.129
2 Kim 198.16.15.254
3 Jessie 192.168.25.200
A mutate
call may need some explanation. I'll try to come back to this thread and break it down when I have more time. Essentially, it does what I outlined earlier:
split
splits IP into 4 parts
In the next call for num
, working inside out, I extract 4th element of the list with purrr::map
, unlist the result with unlist
, and convert the character into an integer.
I then filter to leave only rows as per your condition
Finally, I remove helper columns.
Hope this helps
This is yet another way to do it, but with regex
library(dplyr)
IP_LIST <- data.frame(stringsAsFactors = FALSE,
User = c("John", "Carl", "Mary",
"Kim", "Jane", "Jessie",
"Peter"),
IP = c('172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10') )
IP_LIST %>%
mutate(last_octet = as.numeric(substring(IP_LIST$IP, regexpr("\\.[0-9]+$", IP_LIST$IP) + 1))) %>%
filter(last_octet >= 128)
#> User IP last_octet
#> 1 Mary 172.16.2.129 129
#> 2 Kim 198.16.15.254 254
#> 3 Jessie 192.168.25.200 200
jdlong
January 28, 2019, 3:53pm
7
Luiz:
IP_LIST <- data.frame( "User" = c("John", "Carl", "Mary", "Kim", "Jane", "Jessie", "Peter"), "IP" = c('172.16.0.15', '192.168.200.90', '172.16.2.129', '198.16.15.254', '172.25.25.19', '192.168.25.200', '192.129.200.10') )
I think using dplyr
is a pretty good way to do this. I'd use separate
to pull the IP address into its pieces then a filter:
library(tidyverse)
IP_LIST <- data.frame(
"User" = c("John", "Carl", "Mary",
"Kim", "Jane", "Jessie",
"Peter"),
"IP" = c(
'172.16.0.15',
'192.168.200.90',
'172.16.2.129',
'198.16.15.254',
'172.25.25.19',
'192.168.25.200',
'192.129.200.10'
)
)
IP_LIST %>%
separate(IP, c("o1", "o2", "o3", "o4"), remove = FALSE) %>%
filter(as.numeric(o4) >= 128)
#> User IP o1 o2 o3 o4
#> 1 Mary 172.16.2.129 172 16 2 129
#> 2 Kim 198.16.15.254 198 16 15 254
#> 3 Jessie 192.168.25.200 192 168 25 200
Created on 2019-01-28 by the reprex package (v0.2.1)
1 Like
system
Closed
February 7, 2019, 7:58pm
8
This topic was automatically closed 7 days after the last reply. New replies are no longer allowed. If you have a query related to it or one of the replies, start a new topic and refer back with a link.