web-dev-qa-db-ja.com

すべての英字が大文字かどうかを検出する正規表現

文字列内のすべての英字(> = 2文字)が大文字であるかどうかを検出するにはどうすればよいですか?最終的に、章のタイトル名(データセットの行)を除外しようとしています。したがって、チャプターのタイトルが「ARYA」の場合、「THE QUEEN'S HAND」と同じように、それを検出してほしい。

これが私が試していることですが、うまくいきません:

_library(dplyr)
library(stringr)

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

私が必要とする要件:

  • 文字数> =2。これは最終的にこれを使用してチャプター名を除外するためですが、Wordが「I」である行がある場合がありますが、それはチャプターではなく、単なるWordです。これは別のポイントでフィルタリングできますが
  • アルファベット文字またはアポストロフィのみが検出されました。行が「...」である場合がありますが、これは検出されません。ただし、toupper(x) == (x)ソリューションを使用すると、これは「THE QUEEN'S HAND」のようなものと一緒に検出されます。また、「STOP THIS!」のように感嘆符やピリオドが付いているものをすべて削除しようとしています。
15
Evan O.

論理を逆にする

すべての英字は大文字です。

と同じです

単一の英字は小文字ではありません。

コード

このタスクに本当に正規表現を使用したい場合は、次のように記述するだけです。

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

あなたはそれをテストすることができます ここ

文字列の長さを考慮したい場合は、 logical OR を追加できます。

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

あなたはそれをテストすることができます ここ

15
Eric Duminil

おそらく(?)分析の間違った段階でこれを行っています

ASOIAFのテキスト分析を行い、章の見出しを分析から除外しようとしているようですが、分析の間違ったポイントでそれを試みていると思います。章の見出しは、常にページの上部にあり、常に中央に配置され、常にギャップが続くため、元のテキストで簡単に識別できます。これらの機能を使用すると、見出しを簡単かつ確実に識別できますが、この情報は、見出しを識別しようとする前に破棄されています。分析のこの段階を制御している場合は、代わりに、この段階で見出しとなっているエントリを特定する方が簡単です。

これを行うために正規表現は必要ありません

質問のタイトルでRegexを指定しますが、それは質問の本文には含まれていません。したがって、実際にはそれを必要とせず、不要な問題のRegexソリューションを探しているだけだと思います。

すべての大文字をテストする最も簡単な方法は、x == toupper(x)を実行することです。 toupper()は、すべてのアルファベット文字を大文字の形式に変換します。次に、この変換されたバージョンと比較して、文字列がすべて大文字かどうかをテストできます。

2未満の長さの文字列のスクリーニングも簡単です。nchar(x) >=2条件を追加するだけでこれを実行できます。

最終的な要件はそれほど簡単ではありませんが、除外する必要がある条件を正確に把握する必要があります。完全な段落(?)を取得している場合は、引用符を探すことをお勧めします。一致させる必要のあるオプションの範囲によっては、結局、ここで正規表現を使用する必要があるかもしれませんが、それが特定のマークのみの場合は、_str_detect_(stringrパッケージから)をfixed()これを検出するオプション。これはかなり高速になります。

この最終段階でRegexを使用するかどうかに関係なく、1つのRegex検索を実行するのではなく、関数内の一連の条件に検出をラップします。これにより、高速であり、概念的には理解が容易になると思います。

13
Jack Aidley

編集:

私は最初、小文字が2文字未満の場合は無視することを考えました。 allが大文字であることを確認したい場合は、wholeの長さが文字列は> = 2であり、はるかに単純な正規表現で実行できます。

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

デモ

または、長さが> = 2の文字列と一致させたい場合でも文字が1つだけ含まれている場合(たとえば、「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,}:前の文字と2回以上一致します。
    • (?::2番目の非キャプチャグループの開始。
      • [^A-Za-z\r\n]英語文字または行末記号ではない任意の文字に一致します。2
      • |:または。
      • [A-Za-z]:任意の英語文字に一致します。
      • (?!:否定先読みの開始。
        • [a-z]:小文字の英語に一致します。4
      • ):否定先読みの終わり。
    • ):2番目の非キャプチャグループの終わり。
    • *:前のグループの0回以上一致します。
  • ):最初の非キャプチャグループの終わり。
  • +:前のグループと1回以上一致します。
  • $:行/文字列の終わりに位置をアサートします

注:文字列全体を1行として扱うには、\r\n部分。


  1. 使用する [[:upper:]]代わりに、英語以外の文字を照合する場合。
  2. 使用する [^[:alpha:]\r\n]代わりに、英語以外の文字を照合する場合。
  3. 使用する [[:alpha:]]代わりに、英語以外の文字を照合する場合。
  4. 使用する [[:lower:]]代わりに、英語以外の文字を照合する場合。
10

私がこれを理解する方法:

  • 文字列全体の長さが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
5
muru

[〜#〜]編集[〜#〜]

文字列の文字数を処理するために、正規表現を変更せずにncharifelseとともに使用できます。

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がコメントしたように、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
4
Ronak Shah

私があなたの質問を正しく理解している場合は、次のような文字列を受け入れます。

  1. 2文字以上である。
  2. 小文字を含めないでください。

それが正しければ、あなたは正解からほど遠くない。ただし、小文字以外の文字を受け入れる代わりに、大文字のみを受け入れます。

次の正規表現が機能するはずです。

^[^[:lower:]]{2,}+$
3
Édouard

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
2
andrew_reece