/ / Espressione regolare per mantenere un conteggio progressivo di singoli caratteri - regex, r

Espressione regolare per mantenere un conteggio progressivo di singoli caratteri - regex, r

Considera il seguente vettore x

x <- c("000a000b000c", "abcd00ab", "abcdefg", "000s00r00g00t00")

Usando una singola espressione regolare, mi piacerebbe mantenere solo quegli elementi di x che contengono più di tre lettere. Ecco le regole:

  1. Le lettere non sono sempre consecutive (questo è il problema principale)
  2. Gli elementi stringa di x può avere qualsiasi numero di caratteri
  3. Non ci sarà nulla nella stringa tranne cifre e lettere minuscole

Il modo semplice in cui ho pensato sarebbe di rimuovere tutto ciò che non è una lettera e quindi prendere il numero di caratteri, qualcosa come il seguente.

x[nchar(gsub("[0-9]+", "", x)) > 3]
# [1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"

So che ci sono dichiarazioni come [a-z]{4,} che trova quattro o più lettere minuscole consecutivelettere. Ma cosa succede se le singole lettere sono sparse sulla stringa? Come posso mantenere un "conteggio progressivo" di lettere in modo tale che quando ne passa tre diventa una non corrispondenza? In questo momento tutto ciò che riesco a pensare è scrivere [a-z]+ un sacco di volte, ma questo può diventare brutto se voglio abbinare diciamo, cinque o più lettere.

Questo mi porta lì, ma puoi vedere come potrebbe essere brutto per stringhe più lunghe.

grep("[a-z]+.*[a-z]+.*[a-z]+.*[a-z]+.*", x)
# [1] 2 3 4

C'è un modo per farlo con una migliore espressione regolare?

risposte:

5 per risposta № 1

Prova questo dove \D corrisponde a una non cifra, .* corrisponde a una stringa di 0 o più caratteri e (...){4} dice di abbinare quattro volte, cioè più di 3.

grep("(\D.*){4}", x, value = TRUE)

Ciò corrisponderà se ci sono 4 o un numero maggiore di non cifre. Sostituisci 4 con 6 se hai bisogno di più di 5. Se è importante avere il numero 3 nella regexp, prova questo schema (\D.*){3}\D anziché.


5 per risposta № 2

C'è un operatore di ripetizione che puoi usare: {n} corrisponde al token o al gruppo precedente n volte. Per rendere le corrispondenze più efficienti, dovresti anche essere specifico in ciò che può essere abbinato tra lettere (nel tuo caso solo cifre, non "qualsiasi" carattere (che il punto . partite)):

^(?:[0-9]*[a-z]){4}[0-9a-z]*$

corrisponde a tutte le stringhe che contengono almeno 3 lettere minuscole.

Spiegazione:

^         # Start of string
(?:       # Start of a (non-capturing) group:
[0-9]*   # Match any number of digits
[a-z]    # Match one lowercase ASCII letter
){4}      # Repeat the group exactly four times
[0-9a-z]* # Then match any following digits/letters
$         # until the end of the string

In R:

grep("^(?:[0-9]*[a-z]){4}[0-9a-z]*$", x, perl=TRUE, value=TRUE);

ti dà un vettore di carattere con tutti gli elementi che corrispondono alla regex.


3 per risposta № 3

Il comando grep sotto troverà gli elementi che hanno quattro o più lettere

> grep("^(?:[^a-z]*[a-z]){4}", x, perl=T, value=T)
[1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"

O

> grep("^(?:[^a-z]*[a-z]){3}[^a-z]*[a-z]", x, perl=T, value=T)
[1] "abcd00ab"        "abcdefg"         "000s00r00g00t00"

Per trovare gli elementi con 5 o più lettere,

> grep("^(?:[^a-z]*[a-z]){5}", x, perl=T, value=T)
[1] "abcd00ab" "abcdefg"

Spiegazione:

^                        the beginning of the string
(?:                      group, but do not capture (4 times):
[^a-z]*                  any character except: "a" to "z" (0 or
more times)
[a-z]                    any character of: "a" to "z"
){4}                     end of grouping