我对将文本标记生成器从Ruby移植到R感兴趣,我不能只使用system()
函数从R中调用Ruby扫描程序。现有的Ruby实现大量使用了Ruby的StringScanner
类中的一些方法,我需要弄清楚如何在R中做同样的事情。
想象一下,字符串是一个流,其指针最初指向字符串的开头;我需要的四个操作是:
scan
:如果流当前与指定的正则表达式匹配,请将其拉出,或返回NULL。scan_until
:在流中移动,直到指定的正则表达式匹配。 (我不需要介入文本,但Ruby返回它)getch
:将流向前移动一个字符并将其返回。eos?
:如果指针位于流的末尾,则返回true。我并不挑剔底层对象代表R中的流;一个字符串就可以了,但是在文件连接上运行会很好。
答案 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;。