Regex, чтобы определить, являются ли все буквы алфавита верхними.

Как мне узнать, все ли буквы алфавита в строке (>> 2 символа) являются верхним регистром? В конечном счете, я пытаюсь отфильтровать названия заголовков разделов, которые являются строками в моем наборе данных. Поэтому, если заголовок главы "ARYA", я хочу, чтобы это было обнаружено так же, как "THE QUEEN HAND".

Здесь то, что я пытаюсь, но не работает:

library(dplyr)
library(stringr)

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

Требования, которые мне нужны:

  • Количество символов> = 2, потому что я в конечном счете использую это, чтобы отфильтровать названия разделов, но иногда есть строка, где слово "Я", но это не глава - это просто слово. Хотя это можно было отфильтровать в другом месте
  • Обнаружены только алфавитные символы или апострофы. Иногда строка "...", которую я не хочу обнаружить. Однако, если я использую решение toupper(x) == (x), это будет обнаружено рядом с чем-то вроде "THE QUEEN HAND". Я также пытаюсь избавиться от чего-либо с восклицательными знаками или периодами, например "ОСТАНОВИТЕ ЭТО!".

Ответы

Ответ 1

Обрати свою логику

все алфавитные символы - это верхний регистр.

такой же как

ни один алфавитный символ не является строчным.

Код

Если вы действительно хотите использовать регулярное выражение для этой задачи, все, что вам нужно написать, это:

! str_detect("THE QUEENS HAND", "[[:lower:]]")

Вы можете проверить его здесь.

Если вы хотите взять длину строки во внимание, вы можете добавить логическое ИЛИ:

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

Вы можете проверить его здесь.

Ответ 2

Вы, вероятно, (?) Делаете это на неправильной стадии анализа

Похоже, вы пытаетесь сделать текстовый анализ ASOIAF и исключить заголовки глав из своего анализа, но я думаю, что вы пытаетесь сделать это в неправильной точке анализа. Заголовки глав легко идентифицировать в исходном тексте, потому что они всегда находятся в верхней части страницы, всегда сосредоточены и всегда сопровождаются пробелом. Эти функции позволят вам легко и надежно идентифицировать заголовки, но эта информация была выброшена, прежде чем вы попытаетесь определить заголовки. Если вы контролируете этот этап анализа, вам, скорее всего, будет легче определить, какие записи являются заголовками на этом этапе.

Для этого вам не нужно Regex

Хотя вы указываете Regex в заголовке вопроса, он не включен в вопрос, поэтому я предполагаю, что вам это действительно не нужно, но просто закончил поиск решения Regex к проблеме, где это не требуется.

Самый простой способ тестирования для всех заглавных букв - сделать x == toupper(x). toupper() преобразует все алфавитные символы в форму верхнего регистра, затем вы можете проверить, является ли ваша строка верхним регистром, сравнивая ее с этой преобразованной версией.

Вырезать строки длиной менее 2 также легко, вы можете сделать это, просто добавив nchar(x) >=2.

Ваше окончательное требование менее тривиально, но вам нужно будет точно определить, какое условие вы должны исключить. Я подозреваю, что если вы получаете полные абзацы (?), То лучше всего искать кавычки. В зависимости от диапазона параметров, которые необходимо сопоставить, вам может понадобиться использовать Regex здесь, но если это всего лишь несколько специальных меток, вы можете использовать str_detect (из пакета stringr) с опцией fixed() чтобы обнаружить это как это будет значительно быстрее.

Независимо от того, используете ли вы Regex для этого заключительного этапа, я бы обернул детектирование в ряд условных выражений в функции, а не выполнил один поиск в Regex, поскольку это будет быстрее и, на мой взгляд, концептуально легче понять.

Ответ 3

Редактировать:

Сначала я думал, что вы хотите игнорировать строчные буквы, если их длина <2. Если вы хотите удостовериться, что все буквы в верхнем регистре, но только если длина всей строки равна> = 2, это гораздо проще:

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

Демо.

Или если вы хотите совместить строку с длиной> = 2, даже если она содержит только одну букву (например, "A @"):

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

Еще одна демонстрация.


Оригинальный ответ:

Здесь используется только регулярное выражение, которое проверяет только символы в верхнем регистре, если они> = 2:

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

Попробуйте в Интернете.

Или же:

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

Попробуйте в Интернете.

Сломать:

  • ^: Задает позицию в начале строки/строки.
  • (?: Начало первой группы, не связанной с захватом.
    • [AZ]: соответствует любой заглавной букве на английском языке. 1
    • {2,}: Соответствует двум или более раз предыдущему символу.
    • (?: Начало второй группы, не связанной с захватом.
      • [^A-Za-z\r\n]: Соответствует любому символу, который не является английской буквой или терминатором линии. 2
      • | : Или же.
      • [A-Za-z]: соответствует любой английской букве. 3
      • (?!: Начало отрицательного Lookahead.
        • [az]: Соответствует любой строчной английской букве. 4
      • ): Конец отрицательного Lookahead.
    • ): Конец второй группы, не связанной с захватом.
    • *: Соответствует нулю или более раз для предыдущей группы.
  • ): Конец первой группы, не связанной с захватом.
  • +: Соответствует одному или нескольким предыдущим группам.
  • $: Указывает позицию в конце строки/строки

Примечание. Чтобы обрабатывать всю строку как одну строку, просто удалите часть \r\n.


  1. Вместо этого используйте [[:upper:]], если вы хотите совместить буквы, отличные от английского.
  2. Вместо этого используйте [^[:alpha:]\r\n], если вы хотите совместить неанглийские буквы.
  3. Используйте [[:alpha:]] вместо этого, если вы хотите совместить неанглийские буквы.
  4. Вместо этого используйте [[:lower:]], если вы хотите совместить буквы, отличные от английского.

Ответ 4

То, как я это понимаю:

  • если длина всей строки <2, все идет.
  • в противном случае строка может иметь что угодно, кроме символов нижнего регистра.

С этим я думаю, что этого регулярного выражения должно быть достаточно:

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

Которая является дизъюнкцией

  • Одиночный символ, все идет: ^.$
  • Несколько символов, только в нижнем регистре: ^[^[:lower:]]{2,}$

Попытка:

> str_detect("THE QUEENS HAND", "^(.|[^[:lower:]]{2,})$")
[1] TRUE
> str_detect("THE QUEENS 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

Ответ 5

РЕДАКТИРОВАТЬ

Чтобы позаботиться о количестве символов, которые есть в строке, мы можем использовать nchar с ifelse без изменения регулярного выражения.

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

str <- "THE QUEEN 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 HAND", "THE QUEEN HAND", "T")
nchar(str) >= 2 & grepl("^[A-Z]+$" , gsub("[^A-Za-z]","", str))
#[1]  TRUE FALSE FALSE

Оригинальный ответ

Сначала мы заменим все неалфавитные символы пустым пространством ("") на 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 прокомментировал, мы можем сохранить все это как регулярное выражение только с помощью grepl и gsub

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

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

Ответ 6

Если я правильно понял ваш вопрос, вы хотите принять строки, которые:

  1. Есть два символа или дольше.
  2. Не содержать строчные буквы.

Если это правильно, вы не далеко от правильного ответа. Но ваши принимаются только заглавные буквы вместо того, чтобы принимать что-либо, кроме символов нижнего регистра.

Следующее регулярное выражение должно работать:

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

Ответ 7

Чтобы остаться в контексте stringr, используйте str_replace_all чтобы получить только буквы алфавита, а затем str_detect чтобы проверить верхний регистр:

string1 <- "THE QUEENS 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