(编辑 bgoldst '回答;谢谢!)
感谢您抽出时间回答我的问题。
我有一个字符串向量,每个字符串至少包含一个至少包含两个大写字符的单词。
以下是我的矢量摘录,供您参考:
[1] "Avg TSAvg TSThe average tariff score"
[2] "Customer SatisfactionCustomer SatisfactionA guide to how satisfied customers are"
[3] "ProspectsProspectsA guide to the profitability of segments"
[4] "QualityResearch QualityA measure of the quality of the research undertaken"
[5] "IntensityResearch IntensityA measure of the proportion of staff involved in research"
我需要另一个向量,每个字符串中第一个这样的单词的最后大写字符的位置。对于我分享的摘录,我希望得到向量c(7,22,10,8,10)。
目标是获得所有原始字符串的子字符串向量,直到该位置。对于我分享的摘录,我希望获得向量c("Avg TS", "Customer Satisfaction", "Prospects", "Quality", "Intensity")
。
P.S。:试图将一些正则表达式放在一起以获得匹配和match.lengths但是却无法解决这个问题。非常感谢您的帮助。
答案 0 :(得分:1)
您的预期输出与您的口头描述并不完全匹配。请注意,对于第一个示例字符串,第二个大写字母为S
,您的预期输出包含 S
。但是对于所有其他示例字符串,您的预期输出排除第二个资本。
我们可以通过包括从第二个资本开始的所有资本都应该被吞噬的规定来实现预期的产出,直到我们达到序列中的最后一个资本,然后将其排除。可能有零这样的资本吞没,例如在后四个示例字符串中,但可能有一些,例如在Avg TS
示例中。我们称之为第二个资本范围。
注意:我添加了一个额外的测试用例,以涵盖第二个资本范围的情况,该第二个资本范围与单词中的第一个资本分开,并且包含多个资本。
x <- c('Avg TSAvg TSThe average tariff score','Customer SatisfactionCustomer SatisfactionA guide to how satisfied customers are','ProspectsProspectsA guide to the profitability of segments','QualityResearch QualityA measure of the quality of the research undertaken','IntensityResearch IntensityA measure of the proportion of staff involved in research','Ab cDeFGh');
x;
## [1] "Avg TSAvg TSThe average tariff score"
## [2] "Customer SatisfactionCustomer SatisfactionA guide to how satisfied customers are"
## [3] "ProspectsProspectsA guide to the profitability of segments"
## [4] "QualityResearch QualityA measure of the quality of the research undertaken"
## [5] "IntensityResearch IntensityA measure of the proportion of staff involved in research"
## [6] "Ab cDeFGh"
sub(perl=T,'[A-Z]\\w*?[A-Z]*\\K[A-Z].*','',x);
## [1] "Avg TS" "Customer Satisfaction" "Prospects" "Quality" "Intensity" "Ab cDeF"
[A-Z]
匹配。\w*?
非贪婪地跳过零个或多个单词字符。[A-Z]*
贪婪地吞噬。这实现了我的上述规定。[A-Z]
达到第二个资本范围的关键sub()
,因此匹配的任何内容都将从字符串中删除。因此,我们可以使用\K
原子有效地使\K
左侧的所有内容成为正面的后观断言,这意味着它不被视为最终匹配范围的一部分并将被保留。通过将\K
放在[A-Z]*
之后和(最终)[A-Z]
之前,我们有效地捕获整个字符串,但不包括.*
部分,以匹配字符串的其余部分,然后将其剥离。如果您只想在非大写字母 与第一资本分开的范围内应用第二个资本范围条款,那么我们可以将其更改为:
sub(perl=T,'[A-Z]([A-Z]+|\\w*?)\\K[A-Z].*','',x);
## [1] "Avg TS" "Customer Satisfaction" "Prospects" "Quality" "Intensity" "Ab cDe"
在上面的正则表达式中,我删除了[A-Z]*
狼吞虎咽,并对[A-Z]+
段添加了一个前导\\w*?
替换,这基本上意味着我们在第一个之后立即接受第二个资本范围资本,但仅,如果它紧接在第一个资本之后发生。
答案 1 :(得分:0)
我们可以使用gregexpr
来获取数字位置。我们在单词的开头([A-Z]
- 用于单词边界)匹配大写字母(\\b
),然后是0或更多小写字母([a-z]*
),后跟&#34 ; \ K&#34; (\ K保持文本到目前为止匹配整个正则表达式匹配)后跟一个大写字母([A-Z]
)。
i1 <- gregexpr("\\b[A-Z][a-z]*\\K[A-Z]", v1, perl=TRUE)
i2 <- sapply(i1, `[`, 1)
i2
#[1] 6 22 10 8 10
或者使用带有str_locate
library(stringr)
i2 <- str_locate(v1, "[A-Z][a-z]*[A-Z]")[,2]
i2
#[1] 6 22 10 8 10
将其应用于&#39; v2&#39;
i3 <- str_locate(v2, "[A-Z][a-z]*[A-Z]")[,2]
i3
#[1] 6 22 10 8 10 7
并获取子字符串
sub("(?<=[a-z])[A-Z]$", "", substring(v1, 1, i2), perl=TRUE)
#[1] "Avg TS" "Customer Satisfaction" "Prospects" "Quality" Intensity"
sub("(?<=[a-z])[A-Z]$", "", substring(v2, 1, i3), perl=TRUE)
#[1] "Avg TS" "Customer Satisfaction" "Prospects" "Quality" "Intensity" "Ab cDe"
或者不使用任何外观
sub("^([A-Z][a-z]+\\b)?(\\s*([A-Z][A-Z]|[A-Z][a-z]*)).*", "\\1\\2", v1)
#[1] "Avg TS" "Customer Satisfaction" "Prospects" "Quality" "Intensity"
v1 <- c( "Avg TSAvg TSThe average tariff score",
"Customer SatisfactionCustomer SatisfactionA guide to how satisfied customers are",
"ProspectsProspectsA guide to the profitability of segments",
"QualityResearch QualityA measure of the quality of the research undertaken",
"IntensityResearch IntensityA measure of the proportion of staff involved in research")
v2 <- c(v1, "Ab cDeFGh")