如何在R中复制Ruby的StringScanner的一些功能?

时间:2014-09-05 15:59:30

标签: ruby regex r tokenize text-processing

我对将文本标记生成器从Ruby移植到R感兴趣,我不能只使用system()函数从R中调用Ruby扫描程序。现有的Ruby实现大量使用了Ruby的StringScanner类中的一些方法,我需要弄清楚如何在R中做同样的事情。

想象一下,字符串是一个流,其指针最初指向字符串的开头;我需要的四个操作是:

  • scan:如果流当前与指定的正则表达式匹配,请将其拉​​出,或返回NULL。
  • scan_until:在流中移动,直到指定的正则表达式匹配。 (我不需要介入文本,但Ruby返回它)
  • getch:将流向前移动一个字符并将其返回。
  • eos?:如果指针位于流的末尾,则返回true。

我并不挑剔底层对象代表R中的流;一个字符串就可以了,但是在文件连接上运行会很好。

1 个答案:

答案 0 :(得分:1)

这让我意识到我在设计S3类时有多糟糕,但这里有一些功能似乎可以按照你的要求进行操作

getStringScanner <- function(text) {
    structure(list2env(list(text=text, pos=1)),
    class="StringScanner")
}

remaining <- function(x) {
    stopifnot(is(x, "StringScanner"))
    substr(x$text, x$pos, nchar(x$text))
}
restart <- function(x) {
    stopifnot(is(x, "StringScanner"))
    x$pos = 1
}

scan_here<-function(x, re, ...) {
    stopifnot(is(x, "StringScanner"))
    t <- remaining(x)
    m <- regexpr(re, t, ...)
    if(m==1) {
        x$pos = x$pos + attr(m, "match.length")
        regmatches(t,m)
    } else {
        NA
    }
}

scan_until<-function(x, re, ...) {
    stopifnot(is(x, "StringScanner"))
    t <- remaining(x)
    m <- regexpr(re, t, ...)
    if(m>0) {
        x$pos = x$pos + m  -1;
        substr(t, 1, m-1)
    } else {
        NA
    }
}

getch <- function(x, n=1) {
    stopifnot(is(x, "StringScanner"))
    r <- substr(remaining(x), 1, n)
    x$pos = x$pos + n
    r
}

is.eos <- function(x) {
    stopifnot(is(x, "StringScanner"))
    x$pos > nchar(x$text)
}

我确实将scan重命名为scan_here,因为该名称已经有一个基本函数,并且它不是通用的。我还添加了函数来重置解析并提取剩余的字符串。

这是一个示例使用会话

ss <- getStringScanner("Start-Ok-begin-1-2-3-Start")
scan_here(ss, "Start-")
# [1] "Start-"
remaining(ss)
# [1] "Ok-begin-1-2-3-Start"
scan_until(ss, "-2-")
# [1] "Ok-begin-1"
remaining(ss)
# [1] "-2-3-Start"
getch(ss, 2)
# [1] "-2"
getch(ss)
# [1] "-"
remaining(ss)
# [1] "3-Start"
is.eos(ss)
# [1] FALSE
scan_here(ss, "3-Start")
# [1] "3-Start"
is.eos(ss)
# [1] TRUE

希望这至少能给你一个起点。请注意,唯一的事情&#34;特别&#34;这里真的是在environment类的表示中使用StringScanner。这样我就可以更新pos值&#34;就地&#34;。