正则表达式检测所有字母字符是否为大写

时间:2018-05-23 03:16:53

标签: r regex stringr grepl

如何检测字符串中的所有字母字符(> = 2个字符)是否为大写?最后,我试图过滤掉章节标题名称,即我的数据集中的行。因此,如果一个章节标题是" ARYA",我想要检测到,与" THE QUEEN' S HAND"相同。

这是我尝试但不起作用的地方:

library(dplyr)
library(stringr)

str_detect("THE QUEEN’S HAND", "^[[:upper:]]{2,}+$")
#> FALSE

我需要的要求:

  • 字符数> = 2因为我最终使用此字符来过滤掉章节名称,但有时候会出现“#34; I"”这一行,但是' ;不是章节 - 它只是一个词。虽然这可以在不同的点过滤
  • 仅检测到字母字符或撇号。有时排是" ...",我不想检测到。但是,如果我使用toupper(x) == (x)解决方案,则可以检测到此类问题,例如" THE QUEEN' HAND"。我也试图摆脱带有感叹号或句号的东西,例如"停止这个!"

7 个答案:

答案 0 :(得分:15)

反转您的逻辑

  

所有字母字符均为大写字母。

相同
  

不是单个字母字符是小写字母。

代码

如果您真的想使用正则表达式完成此任务,那么您需要编写的是:

! str_detect("THE QUEEN’S HAND", "[[:lower:]]")

您可以对其进行测试here

如果您想考虑字符串长度,可以添加logical OR

nchar(str) < 2 || ! str_detect(str, "[[:lower:]]")

您可以对其进行测试here

答案 1 :(得分:13)

您可能(?)在分析的错误阶段执行此操作

您似乎正在尝试对ASOIAF进行文本分析,并从分析中排除章节标题,但我认为您正试图在分析中的错误点进行。章节标题在原始文本中很容易识别,因为它们始终位于页面顶部,始终居中并始终跟随间隙。这些功能可以让您轻松可靠地识别标​​题,但在您尝试识别标题之前,这些信息已被丢弃。如果您掌握了分析的这一阶段,那么您可能更容易确定在此阶段哪些条目是标题。

您不需要正则表达式来执行此操作

虽然您在问题标题中指定了Regex,但它不包含在问题正文中,因此我假设您实际上并不需要它,但最终只是寻找Regex解决方案来解决不需要的问题。

测试所有大写字母的最简单方法是x == toupper(x)toupper()会将所有字母字符转换为大写字母形式,然后您可以通过将其与此转换后的版本进行比较来测试您的字符串是否全部为大写。

筛选长度小于2的字符串也很简单,只需添加nchar(x) >=2条件即可完成此操作。

您的最终要求不是那么简单,但您需要确切地确定您需要排除的条件。我怀疑如果你得到完整的段落(?)那么最好的方法是寻找引号。根据需要匹配的选项范围,您可能需要在此处使用Regex,但如果只有少数特定标记,则可以使用str_detect(来自stringr包)与{ {1}}检测它的选项,因为它会快得多。

无论你是否在最后阶段使用Regex,我都会将检测包含在函数中的一系列条件中,而不是进行单一的Regex搜索,因为这样会更快,在我看来,概念上更容易理解。

答案 2 :(得分:10)

修改

我最初认为如果长度为<2,则要忽略小写字母。如果你想确保所有这些字母是大写的,但只有当整个字符串的长度是> = 2时,一个更简单的正则表达式才会这样做:< / p>

^(?:[A-Z](?:[^A-Za-z\r\n])*){2,}$

Demo

或者如果你想匹配长度为&gt; = 2 的字符串,即使它只包含一个字母(例如“A @”):

^(?=.{2})(?:[A-Z](?:[^A-Za-z\r\n])*)+$

Another demo

原始回答:

这是一个仅限正则表达式的解决方案,只检查字符是否为大写,如果它们是&gt; = 2:

^(?:[A-Z]{2,}(?:[^A-Za-z\r\n]|[A-Za-z](?![a-z]))*)+$

Try it online

或者:

^(?:[[:upper:]]{2,}(?:[^[:alpha:]\r\n]|[[:alpha:]](?![[:lower:]]))*)+$

Try it online

<强>故障:

  • ^:在行/字符串的开头处断言位置。
  • (?::开始第一个非捕获组。
    • [A-Z]:匹配任何大写的英语字母。 1
    • {2,}:匹配前一个字符的两次或多次。
    • (?::开始第二个非捕获组。
      • [^A-Za-z\r\n]:匹配任何不是英语字母或行终止符的字符。 2
      • |:或。
      • [A-Za-z]:匹配任何英语字母。 3
      • (?!:开始否定的Lookahead。
        • [a-z]:匹配任何小写的英语字母。 4
      • ):负面的Lookahead结束。
    • ):第二个非捕获组的结束。
    • *:匹配前一组的零次或多次。
  • ):第一个非捕获组的结束。
  • +:匹配前一组的一次或多次。
  • $:断言位于行/字符串
  • 末尾的位置

注意:要将整个字符串视为一行,只需删除\r\n部分。

  1. 如果您想匹配非英文字母,请使用[[:upper:]]
  2. 如果您想匹配非英文字母,请使用[^[:alpha:]\r\n]
  3. 如果您想匹配非英文字母,请使用[[:alpha:]]
  4. 如果您想匹配非英文字母,请使用[[:lower:]]

答案 3 :(得分:5)

我理解这一点:

  • 如果整个字符串的长度是&lt; 2,什么都行。
  • 否则,该字符串可以包含除小写字符以外的任何内容。

有了这个,我认为这个正则表达式应该足够了:

^(.|[^[:lower:]]{2,})$

哪个是

的分离
  • 单个字符,任何内容:^.$
  • 多个字符,仅限非小写:^[^[:lower:]]{2,}$

尝试一下:

> str_detect("THE QUEEN’S HAND", "^(.|[^[:lower:]]{2,})$")
[1] TRUE
> str_detect("THE QUEEN’S HaND", "^(.|[^[:lower:]]{2,})$")
[1] FALSE
> str_detect("i", "^(.|[^[:lower:]]{2,})$")
[1] TRUE
> str_detect("I", "^(.|[^[:lower:]]{2,})$")
[1] TRUE
> str_detect("ii", "^(.|[^[:lower:]]{2,})$")
[1] FALSE

答案 4 :(得分:4)

修改

要注意字符串所包含的字符数,我们可以nchar使用ifelse而不更改正则表达式。

str <- "THE QUEEN'S HAND"
ifelse(nchar(str) >= 2 , grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", str)), FALSE)
#[1] TRUE

str <- "THE QUEEN's HAND"
ifelse(nchar(str) >= 2 , grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", str)), FALSE)
#[1] FALSE

str <- "T"
ifelse(nchar(str) >= 2 , grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", str)), FALSE)
#[1] FALSE

或者@Konrad Rudolph评论说我们可以使用逻辑运算符来避免ifelse检查。

str <- c("THE QUEEN'S HAND", "THE QUEEN's HAND", "T")
nchar(str) >= 2 & grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", str))
#[1]  TRUE FALSE FALSE

原始答案

我们首先用空格(&#34;&#34;)替换所有非字母字符gsub,然后将其与toupper进行比较。

text = gsub("[^a-zA-Z]+", "", "THE QUEENS HAND")

text
#[1] "THEQUEENSHAND"

text == toupper(text)
#[1] TRUE

对于小写字母的字符串,它将返回FALSE

text = gsub("[^a-zA-Z]+", "", "THE QUEENs HAND")
text == toupper(text)
#[1] FALSE

正如@SymbolixAU评论的那样,我们只能使用greplgsub

将整个事物保留为正则表达式
grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", "THE QUEEN'S HAND"))
#[1] TRUE

grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", "THE QUEEN's HAND"))
#[1] FALSE

答案 5 :(得分:3)

如果我理解你的问题,你想接受以下字符串:

  1. 是两个字符还是更长。
  2. 不要包含小写字母。
  3. 如果这是正确的,那么你的答案就差不多了。但你的只接受大写字母而不是接受任何小写字符。

    以下正则表达式应该有效:

    ^[^[:lower:]]{2,}+$
    

答案 6 :(得分:2)

要保持在stringr上下文中,请使用str_replace_all仅获取字母字符,然后使用str_detect检查大写字母:

string1 <- "THE QUEEN’S HAND"
string2 <- "T"

string1 %>%
  str_replace_all(., "[^a-zA-Z]", "") %>%
  str_detect(., "[[:upper:]]{2,}")
# TRUE

string2 %>%
  str_replace_all(., "[^a-zA-Z]", "") %>%
  str_detect(., "[[:upper:]]{2,}")
# FALSE