如何用<div> $ ... $ </div>之类的东西替换LaTeX $ ... $和$$ ... $$符号?

时间:2013-12-30 19:04:25

标签: python regex

我目前遇到的问题是Jekyll与Markdown和LaTeX不兼容。所以我有很多关于$\frac{some}{latex}$$$\int^e_v {en} more$$的文章。

如何将$...$替换为<span>$...$</span>,将$$...$$替换为<div>$$..$$</div>

使这项任务变得困难的事情是:

  • ...可能包含换行符。实际上,...可能包含任何内容,$
  • 除外
  • 第一个$<span>$取代,第二个被$</span>取代
  • $...$$$...$$可用于同一文档(但始终至少由一个空格分隔)

编辑:我刚看到我也需要一些逃脱。所以这项任务还有一个难度:

  • \$不应与上述两种情况中的任何一种相匹配。

2 个答案:

答案 0 :(得分:3)

知道你要求使用正则表达式,但是对于你提到的手边处理的边缘情况,你会遇到麻烦。 (如果发布了其他正则表达式解决方案,请将此答案与他们的答案进行比较)。有了这个,可以很容易地改变双和单个TeX标记的行为并在TeX代码中处理转义。这是一个非常简单的pyparsing示例,可以满足您的需求:

from pyparsing import *

D1 = QuotedString("$",escChar='\\')
D2 = QuotedString("$$",escChar='\\')

div_action = lambda x: "<div>$%s$</div>"%x[0]
span_action = lambda x: "<span>$$%s$$</span>"%x[0]
D1.setParseAction(span_action)
D2.setParseAction(div_action)
others  = Word(printables)
grammar = OneOrMore(D2 | D1 | others).leaveWhitespace()

用例:

S = "$\LaTeX$ is worth $$x=\$3.40$$"
print grammar.transformString(S)

,并提供:

<span>$\LaTeX$</span> is worth <div>$$x=$3.40$$</div>

答案 1 :(得分:2)

我们可以通过更换两个步骤来完成此任务:

import re
str = "$rac{some}{latex}$$$\int^e_v {en} more$$\$rac{some}{latex}$$$\int^e_v {en} more$$\n$rac{some}{latex}$\n$$\int^e_v {en} more$$\n\$rac{some}{latex}$\n$$\int^e_v {en} more$$"

#first step:
str = re.sub(r'(?<![\\])\$\$([^\$]+)\$\$', "<div>$$\g<1>$$</div>", str)
#second step:
str = re.sub(r'(?<![\$\\])\$([^\$]+)(?:(?<!\<div\>)(?<!\\)\$)', "<span>$\g<1>$</span>", str)
print str

说明:

第一步:

我们仅在$$次出现时执行替换,将其替换为<div>$$\g<1>$$</div>\g<1>将替换为正则表达式中定义的第一个组。)

str = re.sub(r'(?<![\\])\$\$([^\$]+)\$\$', "<div>$$\g<1>$$</div>", str)

意识到我们正在使用正则表达式 (?<![\\])\$\$([^\$]+)\$\$ regex101 example,其工作方式如下:

  1. (?<![\\]) ...定义我们匹配的内容...前面没有\ [在正则表达式中:(?<![\\])] 。首先,我们说在表达式之前我们不想要\
  2. ... \$\$ ...定义我们必须在字符串的开头出现$$
  3. ... ([^\$]+)定义在上一步 [在正则表达式$] 之后我们想要除[^\$]+之外的所有内容。然后我们将它放入捕获组(...),以便在代码中引用它之后。
  4. ... \$\$毕竟我们完成了表达,说我们必须在字符串的最后发生$$次。

  5. 第二步:

    我们仅在$次出现时执行替换,将其替换为<span>$\g<1>$</span>(同样,\g<1>将替换为正则表达式中定义的第一个组匹配)

    str = re.sub(r'(?<![\$\\])\$([^\$]+)(?:(?<!\<div\>)(?<!\\)\$)', "<span>$\g<1>$</span>", str)
    

    还要意识到我们正在使用其他正则表达式 (?<![\$\\])\$([^\$]+)(?:(?<!\<div\>)(?<!\\)\$)(是的,有点难)regex101 example,它的工作方式如下:

    1. (?<![\$\\]) ...定义我们匹配的内容...前面没有\ a $ [在...正则表达式:(?<![\\\$])] 。首先,我们说我们不想在开头使用\$
    2. ... \$ ...定义我们的字符串需要以一个$
    3. 开头
    4. ... ([^\$]+) ...定义一个捕获组,其中包含$以外的所有内容,以备将来回拨。
    5. ... (?:(?<!\<div\>)(?<!\\)\$)我们说完我们的字符串以$结尾,但前面没有div [在正则表达式中:?<!\<div\>)] 或{{ 1}} [在正则表达式中:\] 。 (然后我们把它全部放到一个非捕获组中,说所有这些只是一件事(?<!\\)

    6. 注意:也许有更有效的方法来获得此结果。