在R中替换标签内文本中的逗号

t5fffqht  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(79)

我有一个文本文件(my.txt),其中包含以下内容,我希望在R中处理这些内容。

Lorem ipsum tag:[value_0], dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01, value_02, value_03].
Ut enim ad minim veniam, tag:[value_04, value_05, value_06, value_07] quis nostrud exercitation, tag:[value_08, value_09, value_10].

字符串
我希望处理标记(tag:[ * ])内的字符串。标记内的值以逗号分隔,由字母数字字符和标点符号组成(逗号和括号除外)。标记内的值的数量是可变的(1或更多)。我希望使用]+[更改逗号。
我希望得到的结果如下:

Lorem ipsum tag:[value_0], dolor sit amet,
consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01]+[value_02]+[value_03].
Ut enim ad minim veniam, tag:[value_04]+[value_05]+[value_06]+[value_07] quis nostrud exercitation, tag:[value_08]+[value_09]+[value_10].


我所能想出来的就是捕捉标签的内容。

gsub(
  pattern = paste0(
    "tag:\\[([^]]*)\\]"
  ),
  replacement = "\\1",
  x = readLines("my.txt")
)


我不能简单地查找和替换逗号,因为在标记外有逗号。有没有办法进一步处理\\1,用]+[替换逗号?有没有办法使用base R来实现我的目标?
非常感谢

w80xi6nr

w80xi6nr1#

你可以使用嵌套替换的stringr包来实现这一点。首先找到标签,然后为每个标签替换逗号。str_replace_all允许你传递一个函数来进行转换,而不是一个字符串。

input <- c(
  "orem ipsum tag:[value_0], dolor sit amet",
  "consectetur adipiscing elit",
  "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01, value_02, value_03].",
  "Ut enim ad minim veniam, tag:[value_04, value_05, value_06, value_07] quis nostrud exercitation, tag:[value_08, value_09, value_10]."
)

stringr::str_replace_all(input, "tag:\\[[^\\]]*\\]", function(x) {
  stringr::str_replace_all(x, ", ", "]+[")
})

字符串
它返回

[1] "orem ipsum tag:[value_0], dolor sit amet"                                                                                                 
[2] "consectetur adipiscing elit"                                                                                                              
[3] "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01]+[value_02]+[value_03]."                                  
[4] "Ut enim ad minim veniam, tag:[value_04]+[value_05]+[value_06]+[value_07] quis nostrud exercitation, tag:[value_08]+[value_09]+[value_10]."

rsl1atfo

rsl1atfo2#

这里有一些解决方案。
在问题中,方括号内的逗号后面总是跟着一个空格,我假设这是一般情况,但如果方括号内的逗号后面可以跟着一个非空格,则在每个解决方案中删除逗号后面的空格。

1)gsubfn这个一行程序使用gsubfn,它查找第一个参数中给出的模式的匹配项,将其传递给第二个参数中的函数(可以指定为公式),并将每个匹配项替换为函数的输出。

在这里,它匹配tag:[,然后是一个字符串,直到下一个最近的],并使用gsub在其中执行所需的替换。

library(gsubfn)

gsubfn("tag:\\[.*?\\]", ~ gsub(", ", "]+[", x), Lines)

字符串

2)gsub它可以在一个gsub中完成,尽管注意下面的警告。它会查找逗号后跟空格后跟任意数量的非方括号后跟右方括号。如果左方括号先出现或没有遇到右方括号,则不会匹配。除了逗号空格之外的所有内容都在零宽度的前瞻范围内--先行部分将不被视为模式的一部分,因此仅替换逗号空格,并且继续处理先行部分以获得更多的逗号和空格字符序列。

(不幸的是,lookbehind不支持重复字符,所以我们不能使用相同的想法来检查前面的tag:[。因此,这不是完全安全的,尽管它的检查似乎对问题中的示例输入足够了,也许对你的实际输入也足够了。
它只使用R。

gsub(", (?=[^][]*\\])", "]+[", Lines, perl = TRUE)

2a)(2)的这个变体比(2)长,但它检查tag:[,并且仍然只使用基数R。它假设输入中没有大括号。如果有大括号,则使用输入中没有的其他字符,例如< and >。首先,它将tag:[...]替换为{...}。然后,它像(2)中一样执行替换,但使用大括号,最后转换回来。

Lines2 <- gsub("tag:\\[(.*?)\\]", "{\\1}", Lines)
Lines3 <- gsub(", (?=[^][{}]*})", "]+[", Lines, perl = TRUE)
gsub("\\{(.*?)\\}", "tag:[\\1]", Lines2)

gwo2fgha

gwo2fgha3#

另一个解决方案(后来的游戏),专门只对括号内的部分有效,而不必对它们进行更多的模式匹配。(我不是说其他答案不好,只是一个有一些特殊性的替代方案)。

txt <- c("Lorem ipsum tag:[value_0], dolor sit amet,", "consectetur adipiscing elit,", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01, value_02, value_03].", "Ut enim ad minim veniam, tag:[value_04, value_05, value_06, value_07] quis nostrud exercitation, tag:[value_08, value_09, value_10].")
expect <- c("Lorem ipsum tag:[value_0], dolor sit amet,", "consectetur adipiscing elit,", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01]+[value_02]+[value_03].", "Ut enim ad minim veniam, tag:[value_04]+[value_05]+[value_06]+[value_07] quis nostrud exercitation, tag:[value_08]+[value_09]+[value_10].")

gre <- gregexpr("\\[[^]]+\\]", txt)
regmatches(txt, gre) <- regmatches(txt, gre) |>
  lapply(gsub, pattern = ", *", replacement = "]+[")
txt
# [1] "Lorem ipsum tag:[value_0], dolor sit amet,"                                                                                               
# [2] "consectetur adipiscing elit,"                                                                                                             
# [3] "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua tag:[value_01]+[value_02]+[value_03]."                                  
# [4] "Ut enim ad minim veniam, tag:[value_04]+[value_05]+[value_06]+[value_07] quis nostrud exercitation, tag:[value_08]+[value_09]+[value_10]."
identical(txt, expect)
# [1] TRUE

字符串
Regex:

"\\[[^]]+\\]"
 ^^^     ^^^  the literal brackets, escaped since they are used for regex classes
    ^^^^^     one or more of anything other than the close bracket


gregexpr返回一个字符范围的列表,regmatches本身检索子字符串(如上所述)。regmatches<-用修改后的字符串替换子字符串,方便的是,新字符串不需要与原始字符串中的每个子字符串相同的字符数。

相关问题