Normal ifade eşleşmesini ayıklayın


112

Bir dizeden bir sayı çıkarmaya çalışıyorum.

Ve böyle bir şey yapmak [0-9]+ipi "aaa12xxx"ve olsun "12".

Şöyle bir şey olacağını düşündüm:

> grep("[0-9]+", "aaa12xxx", value=TRUE)
[1] "aaa12xxx"

Ve sonra anladım ki ...

> sub("[0-9]+", "\\1", "aaa12xxx")
[1] "aaaxxx"

Ama şunu yapan bir tür yanıt aldım:

> sub("[0-9]+", "ARGH!", "aaa12xxx")
[1] "aaaARGH!xxx"

Kaçırdığım küçük bir ayrıntı var.

Yanıtlar:


167

Tutarlı bir sözdiziminde çalışan tüm mevcut düzenli ifadeleri saran ve eksik olan birkaçını ekleyen yeni stringr paketini kullanın:

library(stringr)
str_locate("aaa12xxx", "[0-9]+")
#      start end
# [1,]     4   5
str_extract("aaa12xxx", "[0-9]+")
# [1] "12"

3
(neredeyse) tam olarak ihtiyacım olan şeydi, ama yazmaya başladığımda ?str_extractgördüm str_extract_allve hayat yeniden güzeldi.
dwanderson

94

' Standart işlevleri görmezden gelin' demek biraz acelecidir ?gsub- 'Ayrıca bkz.' Bölümündeki özel referanslar için bile yardım dosyası :

"regexpr", "gregexpr" ve "regexec" sonuçlarına dayalı olarak eşleşen alt dizeleri çıkarmak için "regmatches".

Yani bu işe yarayacak ve oldukça basit:

txt <- "aaa12xxx"
regmatches(txt,regexpr("[0-9]+",txt))
#[1] "12"

27

Olabilir

gsub("[^0-9]", "", "aaa12xxxx")
# [1] "12"

15

PERL normal ifadelerinin geç eşlemesini kullanabilirsiniz:

> sub(".*?([0-9]+).*", "\\1", "aaa12xx99",perl=TRUE)
[1] "12"

Rakam olmayanları değiştirmeye çalışmak bu durumda bir hataya yol açar.


4
Biraz daha çirkin olan "[^ 0-9] * ([0-9] +). *"
Jyotirmoy Bhattacharya

5

Bunun bir yolu şudur:

test <- regexpr("[0-9]+","aaa12456xxx")

Şimdi, regexpr'in size dizenin başlangıç ​​ve bitiş endekslerini verdiğine dikkat edin:

    > test
[1] 4
attr(,"match.length")
[1] 5

Böylece bu bilgiyi substr işlevi ile kullanabilirsiniz

substr("aaa12456xxx",test,test+attr(test,"match.length")-1)

Eminim bunu yapmanın daha zarif bir yolu vardır, ama bulabildiğim en hızlı yol buydu. Alternatif olarak, istediğinizi bırakmak istemediklerinizi çıkarmak için sub / gsub kullanabilirsiniz.


5

Normal ifadede parantez yakalama ve değiştirmede grup referansları kullanın. Parantez içindeki her şey hatırlanır. Ardından ilk öğe olan \ 2 tarafından erişilir. İlk ters eğik çizgi, normal ifade ayrıştırıcısına iletilmesi için ters eğik çizginin R'deki yorumundan kaçar.

gsub('([[:alpha:]]+)([0-9]+)([[:alpha:]]+)', '\\2', "aaa12xxx")

2

Gsubfn paketinde strapply kullanma. strapply, nesnenin bir dizi vektörü olması (bir dizi yerine) ve değiştiricinin (bir kenar boşluğu yerine) normal bir ifade olması dışında bağımsız değişkenlerin nesne, değiştirici ve işlev olması açısından uygulama gibidir:

library(gsubfn)
x <- c("xy13", "ab 12 cd 34 xy")
strapply(x, "\\d+", as.numeric)
# list(13, c(12, 34))

Bu, x'in her bir bileşeninde her eşleşmeyi sayısal olarak geçen bir veya daha fazla rakamı (\ d +) eşleştirmeyi söyler. Bileşenleri x'in ilgili bileşenlerinin eşleşmelerinin vektörleri olan bir liste döndürür. Çıktıya baktığımızda, x'in ilk bileşeninin 13 olan bir eşleşme ve x'in ikinci bileşeninin 12 ve 34 olan iki eşleşme olduğunu görüyoruz . Daha fazla bilgi için http://gsubfn.googlecode.com adresine bakın .


1

Başka bir çözüm:

temp = regexpr('\\d', "aaa12xxx");
substr("aaa12xxx", temp[1], temp[1]+attr(temp,"match.length")[1])

1

Bu soru için bir çözüm

library(stringr)
str_extract_all("aaa12xxx", regex("[[:digit:]]{1,}"))
# [[1]]
# [1] "12"

[[: digit:]] : rakam [0-9]

{1,} : En az 1 kez eşleşir


0

Bu yaklaşımlar arasındaki önemli bir fark, eşleşmeyen davranışlara yaklaşımdır. Örneğin, tüm konumlarda bir eşleşme yoksa, regmatches yöntemi, girişle aynı uzunlukta bir dize döndürmeyebilir

> txt <- c("aaa12xxx","xyz")

> regmatches(txt,regexpr("[0-9]+",txt)) # could cause problems

[1] "12"

> gsub("[^0-9]", "", txt)

[1] "12" ""  

> str_extract(txt, "[0-9]+")

[1] "12" NA  

0

Ambalaj tutkalını kullanarak aşağıdakileri yapardık :

# install.packages("unglue")
library(unglue)
unglue_vec(c("aaa12xxx", "aaaARGH!xxx"), "{prefix}{number=\\d+}{suffix}", var = "number")
#> [1] "12" NA

2019-11-06 tarihinde reprex paketi tarafından oluşturuldu (v0.3.0)

convertOtomatik olarak bir sayıya dönüştürmek için bağımsız değişkeni kullanın :

unglue_vec(
  c("aaa12xxx", "aaaARGH!xxx"), 
  "{prefix}{number=\\d+}{suffix}", 
  var = "number", 
  convert = TRUE)
#> [1] 12 NA

-2

Regex işlevlerinizi C ++ ile yazabilir, bir DLL'de derleyebilir ve R'den çağırabilirsiniz.

    #include <regex>

    extern "C" {
    __declspec(dllexport)
    void regex_match( const char **first, char **regexStr, int *_bool)
    {
        std::cmatch _cmatch;
        const char *last = *first + strlen(*first);
        std::regex rx(*regexStr);
        bool found = false;
        found = std::regex_match(*first,last,_cmatch, rx);
        *_bool = found;
    }

__declspec(dllexport)
void regex_search_results( const char **str, const char **regexStr, int *N, char **out )
{
    std::string s(*str);
    std::regex rgx(*regexStr);
    std::smatch m;

    int i=0;
    while(std::regex_search(s,m,rgx) && i < *N) {
        strcpy(out[i],m[0].str().c_str());
        i++;
        s = m.suffix().str();
    }
}
    };

R olarak ara

dyn.load("C:\\YourPath\\RegTest.dll")
regex_match <- function(str,regstr) {
.C("regex_match",x=as.character(str),y=as.character(regstr),z=as.logical(1))$z }

regex_match("abc","a(b)c")

regex_search_results <- function(x,y,n) {
.C("regex_search_results",x=as.character(x),y=as.character(y),i=as.integer(n),z=character(n))$z }

regex_search_results("aaa12aa34xxx", "[0-9]+", 5)

4
Bu tamamen gereksizdir. R'nin içinde kolay bir çözüm için "kısa mesaj" veya "Robert" yanıtlarına bakın.
Daniel Hoop
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.