我在Ubuntu中使用R,并尝试查看文件列表,其中一些是我需要的,其中一些我不需要,
我试图通过在其中找到一个子字符串来获得我需要的那个,它需要恰好出现一次,
我正在使用grep这个函数,我在这里找到了grep function in r
并使用我在此处找到的正则表达式规则regex rules
并采用简单的例子
a <- c("a","aa")
grep("a{1}", a)
我希望只获得包含&#34; a&#34;恰好一次,而不是它,我得到了他们两个。
当我使用2代替1时,我确实得到了一个字符串的所需结果(包含&#34; aa&#34;)
我无法使用$,因为这不是我需要的单词的结尾,例如我需要接受这两个单词&#34; germ-pass.tab&#34;,&# 34; germ-pass_germ-pass.tab&#34;并且只返回第一个包含&#34; germ-pass&#34;只有一次
我不能使用^ a因为我不需要像#&#34; aca&#34;
感谢。
答案 0 :(得分:3)
正如我在评论中所说的那样,grep
在你的字符串中查找一个模式,并且确实存在“a”(或“a {1}”,这对于grep
来说是相同的) AA”。您需要在模式中添加“a”后面不是:"a[^a]"
:
grep("a[^a]", c("aa", "ab"), value=TRUE)
#[1] "ab"
修改的
考虑到你的具体问题,似乎你可以尝试“反面”:使用模式的“捕获”过滤掉包含多个模式出现的字符串:
!grepl("(ab).+\\1", c("ab.t", "ab-ab.t"))
#[1] TRUE FALSE
!grepl("(ab).*\\1", c("ab", "ab-ab","ab-cc-ab", "abab"))
#[1] TRUE FALSE FALSE FALSE
括号允许捕获模式(此处ab
但可以是任何正则表达式),.*
用于“任何”零次或多次,\\1
要求重复捕获的模式
答案 1 :(得分:3)
a
但不是aa
您可以使用以下TRE正则表达式:
^[^a]*a[^a]*$
它匹配字符串的开头(^
),除了a
([^a]*
)以外的0 +字符,a
,再次0+非'a'和字符串的结尾($
)。见IDEONE demo:
a <- c("aca","cac","a", "abab", "ab-ab", "ab-cc-ab")
grep("^[^a]*a[^a]*$", a, value=TRUE)
## => [1] "cac" "a"
a
但不包含aa
如果您需要匹配单词,只有一个a
,而不是两个或更多a
位于任何位置。
使用此PCRE正则表达式:
\b(?!\w*a\w*a)\w*a\w*\b
请参阅this regex demo。
<强>解释强>:
\b
- 字边界(?!\w*a\w*a)
- 如果在字边界之后有0个字母字符,a
,0 +字字符和a
,则会出现否定前瞻字母\w*
- 0+ word chars a
- a
\w*
- 0+ word chars \b
- 尾随字边界。 注意:由于\w
与字母,数字和下划线匹配,您可能需要将其更改为\p{L}
或[^\W\d_]
(仅匹配字母)。< / p>
请参阅this demo:
a <- c("aca","cac","a")
grep("\\b(?!\\w*a\\w*a)\\w*a\\w*\\b", a, perl=TRUE, value=TRUE)
## => [1] "cac" "a"
答案 2 :(得分:3)
看起来你只追求一个a
的字符串,而不管字符串中的哪个位置。虽然stringi
可以完成任务,但基本解决方案是:
s <- c("a", "aa", "aca", "", "b", "ba", "ab")
m <- gregexpr("a", s)
s[lengths(regmatches(s, m)) == 1]
[1] "a" "ba" "ab"
或者,正则表达式方法:
s[vapply(strsplit(s, ""), function(x) sum(x == "a") == 1, logical(1))]
[1] "a" "ba" "ab"
答案 3 :(得分:2)
我们可以使用stringi::stri_count
:
library(stringi)
library(purrr)
# simulate some data
set.seed(1492)
(map_chr(1:10, function(i) {
paste0(sample(letters, sample(10:30), replace=TRUE), collapse="")
}) -> strings)
## [1] "jdpcypoizdzvfzs" "gyvcljnfmrzmdmkufq"
## [3] "xqwrmnklbixnccwyaiadrsxn" "bwbenawcwvdevmjfvs"
## [5] "ytzwnpkuromfbklfsdnbwwnlrw" "wclxpzftqgwxyetpsuslgohcdenuj"
## [7] "czkhanefss" "mxsrqrackxvimcxqcqsditrou"
## [9] "ysqshvzjjmwes" "yzawyoqxqxiasensorlenafcbk"
# How many "w"s in each string?
stri_count_regex(strings, "w{1}")
## [1] 0 0 2 3 4 2 0 0 1 1
答案 4 :(得分:1)
我们可以尝试使用^
和$
来确保只有一个&#39; a&#39;在字符串中
grep("^a$", a)
#[1] 1
目前尚不清楚OP想要什么。
答案 5 :(得分:0)
在 base 中,当您用gsub
删除子字符串并测试是否剩余的字符串时,您会找到一个仅包含一次子字符串的字符串。长等于搜索到的子字符串:
s <- c("a", "aa", "aca", "", "b", "ba", "ab", "cac", "abab", "ab-ab", NA)
ss <- "a" #Substring to find exactly once
nchar(s) - nchar(gsub(ss, "", s)) == nchar(ss)
#[1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE NA
或者您统计gregexpr
的点击次数
sapply(gregexpr(ss, s), function(x) sum(x>0)) == 1
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE NA
或已提及@ sebastian-c
lengths(regmatches(s, gregexpr(ss, s))) == 1
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
或带有两个grepl
,一个询问子字符串是否存在一次,另一个询问子字符串是否存在两次:
!grepl("(.*a){2}", s) & grepl("a", s)
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
或一个 regex 中解释的内容,其中(?!(.*a){2})
是非消耗性(零宽度)否定超前行
grepl("^(?!(.*a){2}).*a.*$", s, perl=TRUE)
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
或更笼统,如果您想对其进行更改以恰好找到n次子字符串
!grepl("(.*a){2}", s) & grepl("(.*a){1}", s)
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
grepl("^(?!(.*a){2})(.*a){1}.*$", s, perl=TRUE)
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE
如果只寻找一个字符,则可以使用解决方案表格@wiktor-stribiżew
grepl("^[^a]*a[^a]*$", s)
# [1] TRUE FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE