Give me the users by searching and filtering for 4º octect ip address in R

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

Conceptually, you want to:

  1. Split your IP by . delimiter and get the last (4th) match
  2. Convert the result into an integer for further eval
  3. 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

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

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.