Comment pourrais-je détecter si tous les caractères alphabétiques d'une chaîne (de> = 2 caractères) sont en majuscules? En fin de compte, j'essaie de filtrer les noms de titre de chapitre, qui sont des lignes de mon ensemble de données. Donc, si un titre de chapitre est "ARYA", je veux qu'il soit détecté, comme "LA MAIN DE LA REINE".
Voici ce que j'essaie mais ne fonctionne pas:
library(dplyr)
library(stringr)
str_detect("THE QUEEN’S HAND", "^[[:upper:]]{2,}+$")
#> FALSE
Les exigences dont j'ai besoin:
toupper(x) == (x)
, cela serait détecté à côté de quelque chose comme "LA MAIN DE LA REINE". J'essaie également de me débarrasser de tout ce qui comporte des points ou des points d'exclamation, comme "ARRÊTEZ CECI!tous les caractères alphabétiques sont en majuscules.
est le même que
pas un seul caractère alphabétique n'est en minuscule.
Si vous voulez vraiment utiliser une expression régulière pour cette tâche, tout ce que vous devez écrire est:
! str_detect("THE QUEEN’S HAND", "[[:lower:]]")
Vous pouvez le tester ici .
Si vous souhaitez prendre en compte la longueur de la chaîne, vous pouvez ajouter un OU logique :
nchar(str) < 2 || ! str_detect(str, "[[:lower:]]")
Vous pouvez le tester ici .
Vous faites probablement (?) Cela au mauvais stade de votre analyse
Il semble que vous essayez de faire une analyse textuelle d'ASOIAF et d'exclure les titres de chapitre de votre analyse, mais je pense que vous essayez de le faire au mauvais moment de l'analyse. Les en-têtes de chapitre sont faciles à identifier dans le texte d'origine car ils sont toujours en haut de la page, toujours centrés et toujours suivis d'un espace. Ces fonctionnalités vous permettraient d'identifier facilement et de manière fiable les titres, mais ces informations ont été supprimées avant que vous ne tentiez d'identifier les titres. Si vous contrôlez cette étape de l'analyse, il vous sera probablement plus facile de déterminer quelles entrées sont des en-têtes à ce stade.
Vous n'avez pas besoin de Regex pour cela
Bien que vous spécifiez Regex dans le titre de la question, il n'est pas inclus dans le corps de la question, je suppose donc que vous n'en avez pas réellement besoin mais que vous avez simplement fini par rechercher une solution Regex à un problème où il n'est pas nécessaire.
Le moyen le plus simple de tester toutes les lettres majuscules est de faire x == toupper(x)
. toupper()
convertira tous les caractères alphabétiques dans leur forme majuscule, vous pouvez ensuite tester si votre chaîne est entièrement en majuscule en la comparant à cette version transformée.
Le filtrage des chaînes de longueur inférieure à 2 est également facile, vous pouvez le faire simplement en ajoutant une condition nchar(x) >=2
.
Votre dernière exigence est moins triviale, mais vous devrez déterminer exactement la condition à exclure. Je soupçonne que si vous obtenez des paragraphes complets (?), La meilleure chose serait de rechercher des guillemets. Selon la gamme d'options qui doivent être mises en correspondance, vous devrez peut-être utiliser Regex ici après tout, mais si ce n'est que quelques marques spécifiques, vous pouvez utiliser str_detect
(À partir du package stringr
) avec l'option fixed()
pour le détecter car cela sera considérablement plus rapide.
Peu importe que vous utilisiez Regex pour cette étape finale, j'envelopperais la détection dans une série de conditions dans une fonction plutôt que de faire une seule recherche Regex car cela sera plus rapide et, à mon avis, conceptuellement plus facile à comprendre.
Modifier:
J'ai d'abord pensé que vous vouliez ignorer les lettres minuscules si leur longueur est <2. Si vous voulez vous assurer que toutes les lettres sont en majuscules mais seulement si la longueur de la chaîne entière est> = 2, une expression rationnelle beaucoup plus simple le ferait:
^(?:[A-Z](?:[^A-Za-z\r\n])*){2,}$
Démo .
Ou si vous souhaitez faire correspondre une chaîne de longueur> = 2 même si elle ne contient qu'une seule lettre (par exemple, "A @"):
^(?=.{2})(?:[A-Z](?:[^A-Za-z\r\n])*)+$
Réponse originale:
Voici une solution uniquement regex qui vérifie uniquement si les caractères sont en majuscules s'ils sont> = 2:
^(?:[A-Z]{2,}(?:[^A-Za-z\r\n]|[A-Za-z](?![a-z]))*)+$
Ou:
^(?:[[:upper:]]{2,}(?:[^[:alpha:]\r\n]|[[:alpha:]](?![[:lower:]]))*)+$
Ventilation:
^
: Affirme la position au début de la ligne/chaîne.(?:
: Début du premier groupe non capturant. [A-Z]
: Correspond à n'importe quelle lettre majuscule anglais lettre.1{2,}
: Correspond deux fois ou plus au caractère précédent.(?:
: Début du deuxième groupe non capturant. [^A-Za-z\r\n]
: Correspond à tout caractère qui n'est pas une lettre English ou un terminateur de ligne.2|
: Ou.[A-Za-z]
: Correspond à n'importe quelle lettre English.3(?!
: Début d'un Lookahead négatif. [a-z]
: Correspond à n'importe quelle lettre minuscule anglais lettre.4)
: Fin de l'anticipation négative.)
: Fin du deuxième groupe non capturant.*
: Correspond à zéro ou plusieurs fois du groupe précédent.)
: Fin du premier groupe non capturant.+
: Correspond à une ou plusieurs fois du groupe précédent.$
: Affirme la position à la fin de la ligne/chaîneRemarque: pour traiter la chaîne entière comme une seule ligne, supprimez simplement le \r\n
partie.
[[:upper:]]
à la place, si vous souhaitez faire correspondre des lettres non anglaises.[^[:alpha:]\r\n]
à la place, si vous souhaitez faire correspondre des lettres non anglaises.[[:alpha:]]
à la place, si vous souhaitez faire correspondre des lettres non anglaises.[[:lower:]]
à la place, si vous souhaitez faire correspondre des lettres non anglaises.La façon dont je comprends cela:
Avec cela, je pense que ce regex devrait suffire:
^(.|[^[:lower:]]{2,})$
Quelle est la disjonction de
^.$
^[^[:lower:]]{2,}$
L'essayer:
> 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
MODIFIER
Pour prendre en compte le nombre de caractères de la chaîne, nous pouvons utiliser nchar
avec ifelse
sans changer l'expression régulière.
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
Ou, comme l'a commenté @Konrad Rudolph, nous pouvons éviter la vérification ifelse
en utilisant l'opérateur logique.
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
Réponse originale
Nous remplaçons d'abord tous les caractères non alphabétiques par un espace vide ("") par gsub
, puis le comparons avec toupper
.
text = gsub("[^a-zA-Z]+", "", "THE QUEENS HAND")
text
#[1] "THEQUEENSHAND"
text == toupper(text)
#[1] TRUE
Pour une chaîne en minuscules, elle renverra FALSE
text = gsub("[^a-zA-Z]+", "", "THE QUEENs HAND")
text == toupper(text)
#[1] FALSE
Et comme @SymbolixAU l'a commenté, nous ne pouvons garder le tout en tant que regex qu'en utilisant grepl
et 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
Si je comprends bien votre question, vous souhaitez accepter des chaînes qui:
Si c'est correct, vous n'êtes pas loin de la bonne réponse. Mais la vôtre n'accepte que des lettres majuscules au lieu d'accepter autre chose que des caractères minuscules.
Le regex suivant devrait fonctionner:
^[^[:lower:]]{2,}+$
Pour rester dans le contexte stringr
, utilisez str_replace_all
pour obtenir uniquement les caractères alphabétiques, puis str_detect
pour vérifier les majuscules:
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