2017-12-06 130 views
6

Balansuję kilka wersji R i chcę zmienić moje załadowane biblioteki R w zależności od tego, którego R i używanego systemu operacyjnego używam. Jako takie, chcę trzymać się podstawowych funkcji R.Jak zrobić str_extract z bazą R?

Czytałam tę stronę aby zobaczyć co podstawa R równoważne stringr::str_extract było:

http://stat545.com/block022_regular-expression.html

Sugeruje mogłem replikować tej funkcjonalności z grep. Jednak nie byłem w stanie uzyskać grep, aby zrobić więcej niż zwracać cały ciąg, jeśli jest dopasowanie. Czy jest to możliwe samemu z grep, czy też muszę go łączyć z inną funkcją? W moim przypadku staram się odróżnić CentOS wersjach 6 i 7.

grep(pattern = "release ([0-9]+)", x = readLines("/etc/system-release"), value = TRUE) 
+1

Zobacz https://stackoverflow.com/a/27274231/1017276 – Benjamin

+1

myślę, że to jest dobry konkretne pytanie, które powinien mieć odpowiedź (zamiast zamykania jako dupe, chyba można znaleźć dokładniejsze dopasowanie). Ale proszę zrób dobry przykład, który nie zależy od plików specyficznych dla systemu operacyjnego, aby się odtworzyć. Może nawet pożyczysz niektóre przykłady z '? Str_extract'. – Gregor

+0

Właściwą odpowiedzią jest: każde wyrażenie regularne powinno być dostosowane do użycia z podstawowymi funkcjami wyrażania R. Nie ma uniwersalnego rozwiązania. –

Odpowiedz

9

1) strcapture Jeśli chcesz wyodrębnić ciąg cyfr i kropek od "release 1.2.3" zastosowaniem zasady następnie

x <- "release 1.2.3" 
strcapture("([0-9.]+)", x, data.frame(version = character(0))) 
## version 
## 1 1.2.3 

2) regexec/regmatches Istnieje również regmatches i regexec ale została już omówiona w innej odpowiedzi.

3) sub Również jest to często możliwe użycie sub:

sub(".* ([0-9.]+).*", "\\1", x) 
## [1] "1.2.3" 

3a) Jeśli wiesz, że mecz jest na początku lub na końcu następnie usunąć wszystko przed lub po nim:

sub(".* ", "", x) 
## [1] "1.2.3" 

4) gsub Czasami wiemy, że pole do wyodrębnienia ma określone znaki i nie pojawiają się one gdzie indziej. W takim przypadku po prostu usunąć wszystkie wystąpienia każdej postaci, których nie można w ciągu:

gsub("[^0-9.]", "", x) 
## [1] "1.2.3" 

5) read.table Można często rozkładają wejście na pola, a następnie wybrać się żądany numer jeden przez lub za pośrednictwem grep.strsplit, read.table lub scan można stosować:

read.table(text = x, as.is = TRUE)[[2]] 
## [1] "1.2.3" 

5a) grep/skan

grep("^[0-9.]+$", scan(textConnection(x), what = "", quiet = TRUE), value = TRUE) 
## [1] "1.2.3" 

5b) grep/strsplit

grep("^[0-9.]+$", strsplit(x, " ")[[1]], value = TRUE) 
## [1] "1.2.3" 

6) podciąg Jeśli Znamy postać po żenia pola możemy użyć substring takiego:

substring(x, 9) 
## [1] "1.2.3" 

6a) podciąg/RegExpr lub możemy być w stanie wykorzystać regexpr zlokalizować pozycję znaku dla nas

substring(x, regexpr("\\d", x)) 
## [1] "1.2.3" 

7) read.dcf Czasami istnieje możliwość przekonwertowania danych wejściowych na format DCF, w którym to przypadku można je odczytać za pomocą read.dcf. Takie dane są w postaci name: value

read.dcf(textConnection(sub(" ", ": ", x))) 
##  release 
## [1,] "1.2.3" 
2

Można zrobić

txt <- c("foo release 123", "bar release", "foo release 123 bar release 123") 
pattern <- "release ([0-9]+)" 
stringr::str_extract(txt, pattern) 
# [1] "release 123" NA   "release 123" 
sapply(regmatches(txt, regexec(pattern, txt)), "[", 1) 
# [1] "release 123" NA   "release 123" 
+0

Należy zauważyć, że z 'regexec' nie można używać wzorców PCRE. 'stringr' regex bazuje na ICU i obsługuje rozglądanie się wokół, podczas gdy podstawowy regex R RRE nie działa. –

+0

@ WiktorStribiżew Dobra uwaga. Jednak ustawiając argument "perl" na "TRUE", można również użyć wyrażeń regularnych zgodnych z Perl. – lukeA

+0

@ WiktorStribiżew Zgodnie z dokumentacją 'regexec' obsługuje' perl = TRUE' –

1
txt <- c("foo release 123", "bar release", "foo release 123 bar release 123") 
pattern <- "release ([0-9]+)" 

Extract pierwszy mecz

sapply(
    X = txt, 
    FUN = function(x){ 
     tmp = regexpr(pattern, x) 
     m = attr(tmp, "match.length") 
     st = unlist(tmp) 
     if (st == -1){NA}else{substr(x, start = st, stop = st + m - 1)} 
    }, 
    USE.NAMES = FALSE) 
#[1] "release 123" NA   "release 123" 

Extract wszystkie mecze

sapply(
    X = txt, 
    FUN = function(x){ 
     tmp = gregexpr(pattern, x) 
     m = attr(tmp[[1]], "match.length") 
     st = unlist(tmp) 
     if (st[1] == -1){ 
      NA 
     }else{ 
       sapply(seq_along(st), function(i) substr(x, st[i], st[i] + m[i] - 1)) 
      } 
    }, 
    USE.NAMES = FALSE) 
#[[1]] 
#[1] "release 123" 

#[[2]] 
#[1] NA 

#[[3]] 
#[1] "release 123" "release 123" 
Powiązane problemy