在R语言中匹配多个IP地址与多个CIDR网段
嗨,我来帮你搞定这个iptools的向量不匹配坑!我猜你肯定是想让每个IP都检查所有CIDR网段,但直接用ip_in_cidr()的时候触发了向量长度不匹配的错误——这很正常,因为iptools的向量化函数默认是按位置一一对应匹配的(比如第一个IP配第一个CIDR,第二个IP配第二个CIDR),如果两个列表长度不一样,自然会报错。
下面给你两种实用的解决方法,直接就能用:
方法一:生成所有IP-CIDR组合后批量匹配
这种方法适合你想清晰看到所有匹配关系的场景,用expand.grid生成所有可能的组合,再逐行检查匹配:
library(iptools) library(dplyr) # 你的IP列表和CIDR列表 ips <- c("192.168.100.10", "10.0.0.5", "172.16.3.2") cidrs <- c("192.168.100.0/24", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12") # 生成所有IP和CIDR的组合对 ip_cidr_pairs <- expand.grid(ip = ips, cidr = cidrs, stringsAsFactors = FALSE) # 批量检查每个组合是否匹配 ip_cidr_pairs$is_match <- ip_in_cidr(ip_cidr_pairs$ip, ip_cidr_pairs$cidr) # 筛选出匹配的结果 matched_results <- ip_cidr_pairs %>% filter(is_match) print(matched_results)
运行后你会看到类似这样的结果,清晰展示每个IP对应的匹配网段:
ip cidr is_match
1 192.168.100.10 192.168.100.0/24 TRUE
2 192.168.100.10 192.168.0.0/16 TRUE
3 10.0.0.5 10.0.0.0/8 TRUE
4 172.16.3.2 172.16.0.0/12 TRUE
方法二:用映射函数逐个IP匹配所有CIDR
如果你想直接得到每个IP对应的匹配网段列表,用purrr的map函数更简洁:
library(iptools) library(purrr) # 你的IP列表和CIDR列表 ips <- c("192.168.100.10", "10.0.0.5", "172.16.3.2") cidrs <- c("192.168.100.0/24", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12") # 对每个IP,返回它匹配的CIDR列表 ip_matched_cidrs <- map(ips, ~ cidrs[ip_in_cidr(.x, cidrs)]) # 给结果命名,方便查看 names(ip_matched_cidrs) <- ips print(ip_matched_cidrs)
输出结果会是一个命名列表,直接看到每个IP对应的匹配网段:
$
192.168.100.10
[1] "192.168.100.0/24" "192.168.0.0/16"$
10.0.0.5
[1] "10.0.0.0/8"$
172.16.3.2
[1] "172.16.0.0/12"
为什么会出现向量不匹配?
简单说,iptools的ip_in_cidr()是向量化函数:
- 如果其中一个输入向量长度为1,它会自动“广播”这个值去匹配另一个向量的所有元素(比如单个CIDR匹配多个IP)
- 如果两个向量长度都大于1且不相等,函数不知道该怎么对应匹配,就会抛出向量大小不匹配的错误
所以上面的两种方法本质都是让每个IP都和所有CIDR做匹配,绕开了默认的一一对应逻辑。
内容的提问来源于stack exchange,提问作者Aaron W

