寻找更好的可以进行内部递归的正则表达式

问题描述 投票:0回答:1

我正在翻译一种旧语言(FOCAL)的代码,它使用“()”作为函数参数和向量索引。 目标语言 (R) 也使用“( )”表示函数,但使用“[ ]”表示索引。
FOCAL 变量名称仅限于两个字符,至少在开始时,我假设所有函数名称都有 3 个或更多字符(对于所有内部函数都是如此)。 例如,字符串

" ab(c(kk)) ab(c(5)) sin(x) qr(g) exp(cos(qr)) exp(z) exp(cos(qr(3))) cos(y(3)))  sin(3)"

应转换为

" ab[c[kk] ]  ab[c[5] ]  sin(x) qr[g]  exp(cos(qr)) exp(z) exp(cos(qr[3] )) cos(y[3] ))  sin(3)"  

作为第一个镜头,我首先通过这个正则表达式(R 代码)运行输入来查找数字索引,

str1 <- gsub('([^a-z][a-z]{1,2})[(]([0-9]{1,})[)]' ,'\\1\\[\\2\\] ' , thestr)

接下来我寻找变量名称的索引

str2 <- gsub('([^a-z][a-z]{1,2})[(]([^)]{1,})[)]' ,'\\1\\[\\2\\] ' , str1)

只有当我在第二个正则表达式上递归时才会成功。 我希望有一种更干净的方法,最好是不需要重复操作的方法。

r regex focal
1个回答
0
投票

不清楚一般情况可能是什么,但如果我们修复

cos(y(3)))
中不平衡的括号,那么这适用于显示的输入。 它会在空白处中断输入,然后将
fix_parens
应用于每个组件。 它使用
getParseData
对输入进行标记,然后跟踪
parens
中的括号类型,它替换一两个字符名称及其匹配项后面的括号。 utils 包是 R 自带的,所以不需要安装。

library(utils)

fix_parens <- function(x) {
  txt <- getParseData(parse(text = x))$text
  txt <- txt[txt != ""]
  out <- txt
  paren <- c()
  for(i in seq_along(txt)[-1]) {
    if (nchar(txt[i-1]) %in% 1:2 && txt[i] == "(") {
      paren <- c(paren, "]")
      out[i] <- "["
    } else if (txt[i] == "(") {
      paren <- c(paren, ")")
    } else if (txt[i] == ")") {
      out[i] <- tail(paren, 1)
      paren <- head(paren, -1)
    }
  }
  paste0(out, collapse = "")
}
# same as in question except we fixed the unbalanced parentheses    
inp <- " ab(c(kk)) ab(c(5)) sin(x) qr(g) exp(cos(qr)) exp(z) exp(cos(qr(3))) cos(y(3))  sin(3)"

s <- strsplit(inp, " +")[[1]]
s <- s[s != ""]
paste(unname(sapply(s, fix_parens)), collapse = " ")
## [1] "ab[c[kk]] ab[c[5]] sin(x) qr[g] exp(cos(qr)) exp(z) exp(cos(qr[3])) cos(y[3]) sin(3)"
© www.soinside.com 2019 - 2024. All rights reserved.