分割并重新连接字符串

6

我正在试图从一组字符串中获取IP地址的主机。

ips <- c('140.112.204.42', '132.212.14.139', '31.2.47.93', '7.112.221.238')

我想从IP地址中获取前两个数字。输出:

ips <- c('140.112', '132.212', '31.2', '7.112')

这是我编写的用于转换它们的代码:
cat(unlist(strsplit(ips, "\\.", fixed = FALSE))[1:2], sep = ".")

当我检查最终的单个IP类型时,我会得到类似于以下内容:

140.112 NULL

我不确定我做错了什么。如果你有完全不同的想法,那也完全没问题。

5个回答

4

使用sub函数:

ips <- c('140.112.204.42', '132.212.14.139', '31.2.47.93', '7.112.221.238')

sub('\\.\\d+\\.\\d+$', '', ips)
# [1] "140.112" "132.212" "31.2"    "7.112"

使用来自`stringr`的`str_extract`函数:
library(stringr)
str_extract(ips, '^\\d+\\.\\d+')
# [1] "140.112" "132.212" "31.2"    "7.112"

使用strsplit+sapply方法:
sapply(strsplit(ips, '\\.'), function(x) paste(x[1:2], collapse = '.'))
# [1] "140.112" "132.212" "31.2"    "7.112"

使用read.table + apply

apply(read.table(textConnection(ips), sep='.')[1:2], 1, paste, collapse = '.')
#[1] "140.112" "132.212" "31.2"    "7.112"

注意:

  1. sub('\\.\\d+\\.\\d+$', '', ips):

    i. \\.\\d+\\.\\d+$ 匹配字符串末尾的字面点、一个或多个数字,再跟一个字面点和一个或多个数字

    ii. sub 从字符串中删除上述匹配项

  2. str_extract(ips, '^\\d+\\.\\d+'):

    i. ^\\d+\\.\\d+ 匹配字符串开头的一个或多个数字,一个字面点和一个或多个数字

    ii. str_extract 从字符串中提取上述匹配项

  3. sapply(strsplit(ips, '\\.'), function(x) paste(x[1:2], collapse = '.')):

    i. strsplit(ips, '\\.') 使用字面点作为分隔符拆分每个IP,返回拆分后的向量列表

    ii. 使用sapply对列表中的每个元素应用 paste(x[1:2], collapse = '.') ,因此只取每个向量中的前两个数字,并使用点号将它们合并。然后使用sapply将列表强制转换为向量,从而返回所需的IP向量。

  4. apply(read.table(textConnection(ips), sep='.')[1:2], 1, paste, collapse = '.'):

    i. read.table(textConnection(ips), sep='.')[1:2]ips作为文本输入,并将点号作为分隔符读入。只取前两列。

    ii. apply 启用对每行进行操作的paste,并使用点号合并结果。


1
使用 read.table 函数,您无需使用 apply 函数,可以使用 do.call(paste,c(sep='.',read.table(textConnection(ips), sep='.')[1:2])) - Onyambu
有更大的数据量,我相信 do.call 会胜过 apply。 - Onyambu

4
请尝试以下操作。
gsub("([0-9]+.[0-9]+)(.*)","\\1",ips)

说明:使用gsub函数并在其中放置正则表达式来匹配数字,然后是小数点,再然后是数字,将其存储在内存的第一个位置中,同时将.*之后的所有内容存储在第二个位置中。然后使用\\1替换这些值,该值将是前两个字段。


2

一种解决方案如下:

vapply(strsplit(ips, ".", fixed = TRUE), 
       function(x) paste(x[1:2], collapse = "."), 
       character(1L))
  • vapplystrsplit的输出的每个元素应用 function(x)
  • strsplit 生成一个列表,其中列表的每个元素都是由"."分隔的IP地址组件;设置fixed = TRUE请求使用精确值(即".")而不是使用正则表达式进行拆分
  • function(x) 获取从strsplit出来的每个项目的前两个元素(x [1:2]),并将它们通过"."分隔符连接在一起
  • character(1L) 告诉vapply输出的每个元素(即从function(x)返回的元素)应为长度为1的字符串。

编辑:@useR在我之前发布了这个解决方案(使用sapply)。


1

substr 在停止参数上是矢量化的,因此您可以将其与第二个点之前的位置向量一起使用。 regexpr 给出第一个匹配的位置,因此如果您在第一个匹配中进行了 sub,则可以在第二个匹配上进行匹配 - 这将方便地成为所需位置的前一个(因为您删除了第一个匹配)。

substr(ips,1,regexpr("\\.",sub("\\.","",ips)))
[1] "140.112" "132.212" "31.2"    "7.112"

1
我们可以将IP地址转换为数字版本类,然后使用这个基本的R一行代码进行格式化,它不使用正则表达式:
format(numeric_version(ips)[, 1:2])
[1] "140.112" "132.212" "31.2"    "7.112"  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接