R

时间:2018-01-28 22:47:51

标签: r regex

我正在使用R中的LaTex文档,我需要将{#1 \over #2}更改为\frac{#1}{#2}

使用简单的表达式:

  • {1\over 2}
  • {x^2+y^2\over \lambda}

我可以使用stringr::str_replace()gsub基本函数和正则表达式\\{([\\^a-z0-9\\\\\\s\\+\\-\\*/\(\)]+)\\s*\\\\over\\s*([\\^a-z0-9\\\\\\s\\+\\-\\*/\(\)]+)\\}(我想必须有更好的方法来执行此操作。我尝试使用{{1}但它捕获的比我想要的要多。)

但是当我使用像:

这样的表达式时
  • \\{(.+)\\s*\\\\over\\s*(.*)\\}
  • {e^{2c} \over x-1}

或更复杂的表达:

  • {2yz\over 1+x^{2} }
上面的正则表达式失败了。

是否有正则表达式可以捕获所有替代品?感谢

5 个答案:

答案 0 :(得分:1)

给出一些示例字符串:

> strings
[1] "{1\\over 2}"              "{x^2+y^2\\over \\lambda}"

这个怪物:

 > unlist(
      lapply(
         strsplit(
           sub("\\}$","",
              sub("^\\{","",strings)),"\\\\over"),
          function(x){paste0("\\frac{",x[1],"}{",x[2],"}")}))

产生

 [1] "\\frac{1}{ 2}"              "\\frac{x^2+y^2}{ \\lambda}"

如果源字符串中有多个\over,则会中断。也许在许多其他情况下......哦,如果在第一个{之前或结束}之后有空格,它就不起作用。

在你的其他例子中,你得到了这个:

     in                         out                          
[1,] "{1\\over 2}"              "\\frac{1}{ 2}"             
[2,] "{x^2+y^2\\over \\lambda}" "\\frac{x^2+y^2}{ \\lambda}"
[3,] "{e^{2c} \\over x-1}"      "\\frac{e^{2c} }{ x-1}"     
[4,] "{2yz\\over 1+x^{2} }"     "\\frac{2yz}{ 1+x^{2} }"    

答案 1 :(得分:0)

这可以帮助您完成示例:

library(stringr)

s <- "Expression 1 is {1\\over 2}.

Expression 2 is {x^2+y^2\\over \\lambda}, yes it is.

Expression 3 is {e^{2c} \\over x-1}.

The last expression: {2yz\\over 1+x^{2} }, all done now."

s2 <- str_replace_all(s, 
                      "\\{(.*?)\\s{0,}\\\\over\\s{0,}(.*?)\\}", 
                      "\\frac\\{\\1\\}\\{\\2\\}")

s2
[1] "Expression 1 is frac{1}{2}.\n\nExpression 2 is frac{x^2+y^2}{\\lambda}, yes it is.\n\nExpression 3 is frac{e^{2c}}{x-1}.\n\nThe last expression: frac{2yz}{1+x^{2} }, all done now."

唯一的问题是最后一个表达式中仍然存在空格,这可能不是问题,因为它存在于原始表达式中:

frac{2yz}{1+x^{2} }

答案 2 :(得分:0)

这种方法可以处理:

  • 在同一行包含\ over的多个{...}
  • {...}不包含\ over
  • {...}
  • 出现之前,之后和之间的其他文字
  • 没有任何{...}与的行

例如,请注意下面的示例中第一个出现{...}之前的第二个输入行上的{jjj},其中\ over按预期工作。

它使用可以处理平衡括号的gsubfn。首先创建一个与我的答案here中的原型对象类似的原型对象pp将计数器k初始化为0,并为每个{递增计数器{并为每个递减}。它替换了任何{其中k = 1!还有任何},其中k = 0!

然后将!...\over...!替换为\frac{...}{...},并将剩余的!...!替换为{...}

我们假设了!不会出现在输入中,但如果它确实选择了不同的字符。

library(gsubfn)
library(magrittr)

# test input
s <- c("abc {1\\over 2} def {x^2+y^2\\over \\lambda} ghi { 12 } XYZ",
       "X {jjj} A {e^{2c} \\over x-1} jkl {2yz\\over 1+x^{2} } Z")

# processing

p <- proto(
 pre = function(.) .$k <- 0,
 fun = function(., x) {
  if (x == "{") .$k <- .$k + 1 else if (x == "}") .$k <- .$k - 1
  if (x == "{" && .$k == 1) "!" else if (x == "}" && .$k == 0) "!" else x
})

s %>%
  gsubfn("[{}]", p, .) %>%
  gsub("!([^!]*)\\\\over ([^!]*)!", "\\\\frac{\\1}{\\2}", .) %>%
  gsub("!([^!]*)!", "{\\1}", .)

给出这个结果:

[1] "abc \\frac{1}{2} def \\frac{x^2+y^2}{\\lambda} ghi { 12 } XYZ"
[2] "X {jjj} A \\frac{e^{2c} }{x-1} jkl \\frac{2yz}{1+x^{2} } Z"   

答案 3 :(得分:0)

x=c("{e^{2c} \\over x-1}","{2yz\\over 1+x^{2} },,dty{k^4e{-rpi/3}\\over\\sqrt{2pik}}")

gsub("\\{(.*?)\\\\over(.*?)\\}","\\\frac{\\1}{\\2}",x)

[1] "\frac{e^{2c} }{ x-1}"                                       
[2] "\frac{2yz}{ 1+x^{2} },,dty\frac{k^4e{-rpi/3}}{\\sqrt{2pik}}"

说明:

\{(.*?)\\over(.*?)\\

  • 列表项{匹配字符{字面(区分大小写)

第一捕获组(。*?)

  • 。*?匹配任何字符(行终止符除外)
  • *?量词 - 在零和无限次之间匹配,尽可能少,根据需要扩展(懒惰)

\\匹配    character \ literally(区分大小写)匹配字符    字面意思(区分大小写)

第二捕获组(。*?)

  • 。*?匹配任何字符(行终止符除外)
  • *?量词 - 在零和无限次之间匹配,尽可能少,根据需要扩展(懒惰)

\\匹配字符\字面(区分大小写)

答案 4 :(得分:0)

我很喜欢这个问题。

在某些时候你必须解析文档。来自parse_tex的{​​{1}}考虑到LaTeX不是普通的TeX,但似乎在这里做得不错。对于TeXCheckR的多行实例,虽然原理与我想的相同,但需要更改脚本。

挑战在于持续分数。

    

\over

测试TeX文档:     

library(data.table) # for shift
library(TeXCheckR)  # for parse_tex

locate_over <- function(doc_parsed) {
  lead <- function(x, n) data.table::shift(x, n = n, type = "lead", fill = "")
  char <- .subset2(doc_parsed, "char")
  which(char == "\\" &
          lead(char == "o", 1L) &
          lead(char == "v", 2L) &
          lead(char == "e", 3L) &
          lead(char == "r", 4L))
}


over2frac <- function(lines, verbose = FALSE) {
  out <- lines
  for (i in seq_along(lines)) {
    if (grepl("\\over", lines[i], fixed = TRUE)) {
      i_parsed <- parse_tex(lines[i])

      # Find lhs
      for (j in locate_over(i_parsed)) {
        lhs_start <- max(which(.subset2(i_parsed, "char") %chin% c("$", "{") &
                                 .subset2(i_parsed, "column") < j &
                                 .subset2(i_parsed, "tex_group") == .subset2(i_parsed[j], "tex_group")))

        rhs_end <- min(which(.subset2(i_parsed, "char") %chin% c("$", "}") &
                               .subset2(i_parsed, "column") > j + 4L &
                               .subset2(i_parsed, "tex_group") == .subset2(i_parsed[j], "tex_group")))

        i_parsed[lhs_start, char := "{\\frac{"]
        i_parsed[rhs_end, char := "}}"]
      }
      res <- paste0(i_parsed[["char"]], collapse = "")
      res <- gsub("\\over", "}{", res, fixed = TRUE)
      out[i] <- res
    }
  }
  out
}

产生的LaTeX文档:具有必要的LaTeX特定内容,以及内联分数的强制数学模式。 $5 \over 2$ This is another fraction: ${1 \over 2}$. And another: $$A = a \over b$$ What about: $${{D \over C} \over H}$$ Finally: $${e^{2c} \over x-1}$$ ${2yz\over 1+x^{2} }$ $$\phi = 1 + {1 \over {1 + {1 \over {1 + {1 \over {1 + \ddots}}}}}}$$ \item $Dom\left(Q\right)\ne {\rm R}^{2} $ y uno de los puntos no pertenecientes al dominio es $\left({1\over 2} ,{1\over 2}\right).$ \bye

writeLines(over2frac(readLines("tex1.tex"), verbose = FALSE), "latex1.tex")