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

Eva*_* O. 15 regex r stringr grepl

如何检测字符串中的所有字母字符(> = 2个字符)是否为大写?最后,我试图过滤掉章节标题名称,即我的数据集中的行.因此,如果章节标题是"ARYA",我希望检测到,与"女王的手"相同.

这是我正在尝试但不起作用的:

library(dplyr)
library(stringr)

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

我需要的要求:

  • 字符数> = 2因为我最终使用它来过滤掉章节名称,但有时会出现一行"I"这个词,但这不是章节 - 它只是一个单词.虽然这可以在不同的点过滤
  • 仅检测到字母字符或撇号.有时行是"...",我不想检测到.但是,如果我使用toupper(x) == (x)解决方案,这将与"女王的手"一样被检测到.我也试图摆脱任何带有感叹号或句号的东西,比如"停止这个!"

Eri*_*nil 15

扭转你的逻辑

所有字母字符都是大写字母.

是相同的

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

如果你真的想使用正则表达式完成这项任务,你需要写的只有:

! str_detect("THE QUEEN’S HAND", "[[:lower:]]")
Run Code Online (Sandbox Code Playgroud)

你可以在这里测试一下.

如果要考虑字符串长度,可以添加逻辑OR:

nchar(str) < 2 || ! str_detect(str, "[[:lower:]]")
Run Code Online (Sandbox Code Playgroud)

你可以在这里测试一下.


Jac*_*ley 13

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

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

您不需要Regex来执行此操作

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

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

筛选长度小于2的字符串也很容易,只需添加一个nchar(x) >=2条件就可以做到这一点.

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

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

  • 我做了一些测试,无论组成如何,这都比你的示例长度的字符串的Regex解决方案快7.5倍.对于非常长的字符串(1000个字符),它的速度要快1.2-4.5倍,具体取决于字符串的组成,但对于非常非常长的字符串(100,000个字符),它可能会相当慢或者更快,具体取决于字符串的组成. (2认同)

Ahm*_*eed 10

编辑:

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

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

演示.

或者,如果要匹配长度> = 2的字符串,即使它只包含一个字母(例如,"A @"):

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

另一个演示.


原始答案:

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

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

在线尝试.

要么:

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

在线尝试.

分解:

  • ^:断言行/字符串开头的位置.
  • (?::开始第一个非捕获组.
    • [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:]]相反,如果你想匹配非英文字母.


mur*_*uru 5

我理解这个的方式:

  • 如果整个字符串的长度<2,则任何事情都会发生.
  • 否则,该字符串可以包含除小写字符以外的任何内容.

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

^(.|[^[:lower:]]{2,})$
Run Code Online (Sandbox Code Playgroud)

哪个是脱节

  • 单个字符,任何事情: ^.$
  • 多个字符,仅非小写字母: ^[^[: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
Run Code Online (Sandbox Code Playgroud)


Ron*_*hah 4

编辑

为了处理字符串的字符数量,我们可以使用ncharwithifelse而无需更改正则表达式。

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
Run Code Online (Sandbox Code Playgroud)

或者正如 @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
Run Code Online (Sandbox Code Playgroud)

原答案

我们首先将所有非字母字符替换为空格(“”)gsub,然后将其与 进行比较toupper

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

text
#[1] "THEQUEENSHAND"

text == toupper(text)
#[1] TRUE
Run Code Online (Sandbox Code Playgroud)

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

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

正如 @SymbolixAU 评论的那样,我们可以仅通过使用grepl和将整个事物保留为正则表达式gsub

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
Run Code Online (Sandbox Code Playgroud)