Slovník | Vyhledávání | Mapa webu
 
Základy informatiky pro biologyCvičebnice jazyka R Dokumentace k základním funkcím sub

sub

Srovnávání se vzorem a nahrazování

grep {base} Dokumentace R v češtině

Popis

grep, grepl, regexpr, gregexpr a regexec srovnávají každý prvkek vektoru řetězců s argumentem pattern: funkce se od sebe odlišují ruzným formátem a množstvím detailů ve výsledku.

sub a gsub provádí nahrazení první, respektive všech nalezených shod.

Použití

grep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,
fixed = FALSE, useBytes = FALSE, invert = FALSE)

grepl(pattern, x, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

sub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

gsub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

regexpr(pattern, text, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

gregexpr(pattern, text, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

regexec(pattern, text, ignore.case = FALSE, perl = FALSE,
fixed = FALSE, useBytes = FALSE)

Argumenty

pattern

řetězec znaků obsahující regulární výraz (nebo řetězec znaků pro fixed = TRUE), který má být srovnán se znaky v daném vektoru řetězců. Pokud je to možné a nutné, je nedříve převeden na řetězec znaků funkcí as.character. Pokud je poskytnutý vektro řetězců délky 2 a více, je s varováním použitý pouze první prvek. Chybějící hodnoty jsou povoleny s víjimkou regexpr a gregexpr.

x, text

vektor řetězců, ve kterém jsou prováděna srovnání, nebo jiný objekt, který může být převeden funkcí as.character na vektor řetězců. Dlouhé vektory jsou podporovány.

ignore.case

pokud je FALSE, tak se při srovnávání se vzorem rozlišují velká a malá písmena, v případě TRUE tomu tak během srovnávání není.

perl

logický argument: mají být použity Perl-kompatibilný regulární výrazy?

value

vstahuje se k funkci grep. Pokud je FALSE, je navrácen vektor obsahující (integer) indexy prvků, u kterých ke shodě došlo, je-li TRUE, je navrácen vektor obsahující přímo prvky se shodou.

fixed

logický argument. Pokud je TRUE, je řetězec v pattern brán u srovnání doslovně. Žádné sporné argumenty nebudou brány do úvahy.

useBytes

logický argument. Pokud je TRUE, srovnání je provedeno způsobem bajt po bajtu, ne znak po znaku. Viz ‘Detaily’.

invert

logický argument. Pokud je TRUE, budou navráceny indexy nebo hodnoty prvků, které se neshodovaly.

replacement

náhrada při shodě se vzorem u funkce sub a gsub. Argument je nejdříve převeden na řetězec. U možnosti fixed = FALSE jsou zahrnuty i zpětné odkazy (backreferences) od "1" do "9" na podvýrazy pattern uvedeny v závorce. Pouze u možnosti perl = TRUE může argument obsahovat i "U" nebo "L", což umožňuje převod zbytku řetězce k nahrazení na velká nebo malá písmena, a "E" pro ukončení převodu. Pokud je poskytnutý vektor řetězců o délce 2 a více, je s varováním použitý pouze první prvek. Pokud argument nabývá hodnoty NA, všechny prvky se shodou budou ve výsledku jako NA.

Detaily

Argumenty, které mají být řetězec znaků nebo vektor řetězců, jsou nejdříve převedeny, je-li to možné, na typ character.

Každá ze zmíněných funkcí může pracovat v jednom ze tří následujících módů:

  1. fixed = TRUE: vyhledává přesné shody.

  2. perl = TRUE: používá regulární výrazy stylu Perl.

  3. fixed = FALSE, perl = FALSE: používá POSIX 1003.2 rozšířené regulární výrazy (výchozí nastavení).

Pro více informací o různých typech regulárních výrazů navštivte regular expression.

Funkce sub a gsub se liší v tom, že sub nahrazuje pouze první shodu s pattern, kdežto gsub nahrazuje všechny shody. Pokud replacement obsahuje zpětné odkazy, které nejsou definovány v pattern, je výsledek neurčitý (zpětné odkazy jsou ale nejčastěji brány jako "").

U regexpr, gregexpr a regexec je chybou, pokud se pattern rovná NA, v ostatních případech je hodnota NA povolena a, je-li použita, navrátí vektor shodnotami NA pro každé srovnání.

Hlavním důvodem použití useBytes je, aby se předešlo signalizaci chyb/varovných hlášení u neplatných vstupů a napravým shodám u multibajtových místních nastaveních. Pro funkci regexpr to však mění interpretaci výstupu. Jakákoliv konverze na bajty je u vstupů s označeným kódováním zablokována. Je provedena pouze tam, kde má vstup oznčené kódování "bytes" (viz Encoding).

Ignorování velkých a malých písmen nedává v případě srovnávání bajtů v multibajtovém lokálním nastavení smyl. Měli bychom počítat s tím, že useBytes = TRUE funguje pouze pro znaky ASCII.

regexpr a gregexpr s perl = TRUE umožňuje pojmenované podvýrazy ('named capture') ve stylu Pythonu, nelze však uplatnit u vstupů typu dlouhých vektorů.

Varovné hlášení o neplatných vstupech pro akutuální místní nastavení může nastat až 5 krát.

Srovnávání non-ASCII znaků s ignorováním velkých a malých písmen u možnosti perl = TRUE závisí na knihovně PCRE, která byla sestavena s pomocí ‘Unicode property support’: není tedy potřeba extrení knihovny.

Hodnota

grep(value = FALSE) navrací vektor indexů prvků x, které se shodovaly (nebo neshodovaly, pokud invert = TRUE). Vektor je typu integer. V případě vstupu dlouhého vektoru je to vektor typu double.

grep(value = TRUE) navrací vektor řetězců, který obsahuje prvky z x (po převodu na typ character), u kterých nastala shoda se vzorem (jsou zachovány názvy, nikoliv ostatní vlastnosti).

grepl navrací vektor typu logical (zda se jednotlivé prvky x shodují či neshodují s daným vzorem).

sub a gsub navrací vektor řetězců stejné délky a vlastností jako x (po možném převedení na řetězec). Prvky vektoru řetězců x, které nejsou nahrazeny, budou navráceny nezměněné (včetně deklarovaného kódování). Pokud se useBytes = FALSE, bude výsledek s nahrazenými non-ASCII znaky v UTF-8 se značeným kódováním (např. pokud je vstup v UTF-8 anebo v případě multibajtového místního nastavení, není-li fixed = TRUE). Takový řetězec muže být překódován zpět pomocí enc2native.

regexpr navrací vektor typu integer stejné délky jako text, který nás informuje, na které pozici v prvku došlo ke shodě se vzorem. V přípdě, že nedošlo, je vrácena hodnota -1.Dále pak navrací další vektor typu integer s vlastností "match.length", který udává délku shodovaného textu (pokud nebyla shoda, tak -1). Obojí, pozice i délka, jsou v jednotkách znaků. Pokud se však useBytes = TRUE, jsou v jednotkách bajtů (jelikož je toto srovnávání určeno pouze pro znaky ASCII, může být pro výsledek v obou případech nastavená vlastnost useBytes = TRUE). Pokud jsou použity pojmenované podvýrazy, jsou zpřístupněny další vlastnoosti jako "capture.start", "capture.length" a "capture.names".

gregexpr navrací seznam stejné délky jako text. Každý prvek seznamu má stejný formát jako navrácená hodnota u regexpr. Odlišností je, že došlo-li na více pozicích v prvku ke shodě se vzorem, jsou navráceny všechny pozice shody (nikoliv pouze ta první).

regexec navrací seznam stejné délky jako text, kterého každý prvek je buďto -1, pokud nedošlo ke shodě, nebo posloupnost celých čísel udávajících pozice shody i všech podřetězců, které odpovídají podvýrazům v pattern. Dále je navrácen vektor s vlastností "match.length", který udává délku shody (nebo -1, pokud nebyla žádná shoda). Interpretace pozicí, délek i vlastností je obdobná jako u funkce regexpr.

Pokud srovnávání selže z důvodu limitů zdroje (platí obzvlášť pro PCRE), je na to ve výstupu pohlíženo jako na neshodu, obvykle doprovázené varovným hlášením.

Varování

Mód POSIX 1003.2 u funkcí gsub a gregexpr nepracuje správně s opakujícími se hranicemi slova (např. pattern = "b"). Pro taková srovnávání použijte perl = TRUE (tento mód však nemusí pracovat dle očekávání se vstupy obsahujícími non-ASCII znaky, neboť význam ‘slova’ závisí na systému).

Poznámky k výkonu

Pokud provádíte mnohá srovnávání s pomocí regulárních výrazů, včetně takových na velmi dlouhých řetězcích, budete chtít zvážit, kterou metodu použít. Obvykle je PCRE rychlejší než ostatní regulární stroje, i přes fixed = TRUE (zejména pokud je vzor shodný pouze párkrát).

Pokud pracujete v jednobajtovém místním nastavení a máte řetězce se značeným UTF-8, které mohou být reprezentovány ve zmíněném místním nastavení, tak jejich převod na jeden UTF-8 řetězec příměje provést srovnávání v Unicode.

Pokud máte možnost použít useBytes = TRUE, tak řetězec nebude před srovnáváním kontrolován, což urychlí samotný proces srovnávání. Často je srovnávání založené na bajtech dostačující v místním nastavení UTF-8.

Srovnávání založené na PCRE jako výchozí nastavení vynakládá dodatečné usilí na ‘prozkoumání’ kompilovaného vzoru, má-li x/text délku alespoň 10. Od verze R 3.4.0 může být toto prozkoumání provedeno s použitím kompilátoru PCRE JIT na platformách, kde je k dispozici (viz pcre_config). Detaily lze upřesnit pomocí options PCRE_study a PCRE_use_JIT. (Porovnání časové náročnosti může být provedeno za použití ‘tests/PCRE.R’ ve zdrojých R). Ti, kteří pracují s PCRE a velmi dlouhými řetězci, mohou upravit maximální velikost JIT zásobníku nastavením proměnné prostředí R_PCRE_JIT_STACK_MAXSIZE před použitím JIT na hodnotu mezi 1 a 1000 v MB: výchozí hodnota je 64. (Potom by také bylo vhodné nastavit option PCRE_limit_recursion.)

Zdroj

C kód pro srovnávání za pomocí regulárních výrazů stylu POSIX se v průběhu let změnil. Od verze R 2.10.0 (Říjen 2009) je používána TRE knihovna od Ville Laurikari (http://laurikari.net/tre/). Standard POSIX nechává prostor na interpretaci, zejména obsluhou neplatných regulárních výrazů a porovnáváním znakových sad, tedy výsledky se mohou mírně lišit oproti těm z dřívějška.

Pro srovnávání ve stylu Perl je použito PCRE (http://www.pcre.org): opět se můžou výsledky mírně lišit v závislosti na použité verzi.

Reference

Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) The New S Language. Wadsworth & Brooks/Cole (grep)

Příklad

grep("[a-z]", letters)

txt <- c("arm","foot","lefroo", "bafoobar")
if(length(i <- grep("foo", txt)))
cat("'foo' appears at least once innt", txt, "n")
i # 2 a 4
txt[i]

## Zdvojte všechna 'a' nebo 'b'; "" musí být uniknutý, tzn. 'zdvojený'
gsub("([ab])", "1_1_", "abc and ABC")

txt <- c("The", "licenses", "for", "most", "software", "are",
"designed", "to", "take", "away", "your", "freedom",
"to", "share", "and", "change", "it.",
"", "By", "contrast,", "the", "GNU", "General", "Public", "License",
"is", "intended", "to", "guarantee", "your", "freedom", "to",
"share", "and", "change", "free", "software", "--",
"to", "make", "sure", "the", "software", "is",
"free", "for", "all", "its", "users")
( i <- grep("[gu]", txt) ) # indices
stopifnot( txt[i] == grep("[gu]", txt, value = TRUE) )

## Všimněte si, že v místních nastevních jako en_US, je takto zahrnuto B, protože
## pořadí porovnávání je aAbBcCdDe ...
(ot <- sub("[b-e]",".", txt))
txt[ot != gsub("[b-e]",".", txt)]#- gsub provede "celskové" nahrazení

txt[gsub("g","#", txt) !=
gsub("g","#", txt, ignore.case = TRUE)] # slova "G"

regexpr("en", txt)

gregexpr("e", txt)

## Používání funkce grepl() profiltorvání
## Nalezení funkcí s názvy argumentů shodujících se s "warn":
findArgs <- function(env, pattern) {
nms <- ls(envir = as.environment(env))
nms <- nms[is.na(match(nms, c("F","T")))] # <-- work around "checking hack"
aa <- sapply(nms, function(.) { o <- get(.)
if(is.function(o)) names(formals(o)) })
iw <- sapply(aa, function(a) any(grepl(pattern, a, ignore.case=TRUE)))
aa[iw]
}
findArgs("package:base", "warn")

## zakončení mezerou
str <- "Now is the time "
sub(" +$", "", str) ## spaces only
## Co je myšleno 'bílým znakem' závisí na místním nastavení
sub("[[:space:]]+$", "", str) ## white space, POSIX-style
## To, co považovalo PCRE za bílý znak, se změnilo ve verzi 8.34: viz ?regex
sub("s+$", "", str, perl = TRUE) ## bílý znak stylu PCRE

## Kapitalizace
txt <- "test of capitalization"
gsub("(w)(w*)", "U1L2", txt, perl=TRUE)
gsub("b(w)", "U1", txt, perl=TRUE)

txt2 <- "useRs may fly into JFK or laGuardia"
gsub("(w)(w*)(w)", "U1E2U3", txt2, perl=TRUE)
sub("(w)(w*)(w)", "U1E2U3", txt2, perl=TRUE)

## pojmenované podvýrazy
notables <- c(" Ben Franklin and Jefferson Davis",
"tMillard Fillmore")
# názvy skupin 'first' a 'last'
name.rex <- "(?<first>[[:upper:]][[:lower:]]+) (?<last>[[:upper:]][[:lower:]]+)"
(parsed <- regexpr(name.rex, notables, perl = TRUE))
gregexpr(name.rex, notables, perl = TRUE)[[2]]
parse.one <- function(res, result) {
m <- do.call(rbind, lapply(seq_along(res), function(i) {
if(result[i] == -1) return("")
st <- attr(result, "capture.start")[i, ]
substring(res[i], st, st + attr(result, "capture.length")[i, ] - 1)
}))
colnames(m) <- attr(result, "capture.names")
m
}
parse.one(notables, parsed)

## Rozložení URL na jeho části
## Příklad od LT (http://www.cs.uiowa.edu/~luke/R/regexp.html).
x <- "http://stat.umn.edu:80/xyz"
m <- regexec("^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)", x)
m
regmatches(x, m)
## Prvek 3 je protokol, 4 je host, 6 je port a 7 je umístění
## Můžeme toho využít, pokud potřebujeme vyextrahovat části URL:
URL_parts <- function(x) {
m <- regexec("^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)", x)
parts <- do.call(rbind,
lapply(regmatches(x, m), `[`, c(3L, 4L, 6L, 7L)))
colnames(parts) <- c("protocol","host","port","path")
parts
}
URL_parts(x)

## Zatím nemáme funci gregexec(), ovšem lze ji napodobnit
## spuštěním regexec() na regmatches získaných cestou gregexpr(). Např.:
pattern <- "([[:alpha:]]+)([[:digit:]]+)"
s <- "Test: A1 BC23 DEF456"
lapply(regmatches(s, gregexpr(pattern, s)),
function(e) regmatches(e, regexec(pattern, e)))

 
vytvořil Institut biostatistiky a analýz Lékařské fakulty Masarykovy univerzity