Регулярное выражение, чтобы определить, все ли буквы в верхнем регистре - PullRequest
0 голосов
/ 23 мая 2018

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

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

library(dplyr)
library(stringr)

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

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

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

Ответы [ 7 ]

0 голосов
/ 23 мая 2018

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

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

Для этого вам не нужно регулярное выражение

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

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

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

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

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

0 голосов
/ 23 мая 2018

Обратная логика

все буквенные символы в верхнем регистре.

совпадает с

ни один буквенный символ не являетсястрочные буквы.

Код

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

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

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

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

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

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

0 голосов
/ 23 мая 2018

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

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

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

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

^[^[:lower:]]{2,}+$
0 голосов
/ 23 мая 2018

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

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

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

^(.|[^[: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
0 голосов
/ 23 мая 2018

Чтобы остаться в контексте 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
0 голосов
/ 23 мая 2018

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

Сначала я думал, что вы хотите игнорировать строчные буквы, если их длина <2.Если вы хотите убедиться, что <strong>все буквы в верхнем регистре, но только если длина строки целом > = 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:]]))*)+$

Попробуйте онлайн .

Разбивка:

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

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


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

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

Чтобы определить количество символов в строке, мы можем использовать 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

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

Сначала мы заменяем все не алфавитные символы пробелом ("") на 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'S HAND"))
#[1] TRUE

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