Markdown转LaTeX的Python程序大全(持续更新)
Markdown是做笔记的利器,虽然有
Pandoc
这样的工具,但直接转过去的格式通常是没法直接编译成功的。其中一个最大的问题就是公式的转换。
比如在Markdown里面,写不写\begin{equation}
这样的代码其实都不会自动编号,所以经常在做笔记的时候索性就不想写了。那么此时通常是用双$$
符号来进行公式居中排版,而编号就手动用\tag{1}
这样的方式进行。这种方式在Markdown里一时爽,但转成的时候就非常痛苦了。转换过去的一大通代码无法编译,并且也不好改。当然还有一些非常不同于自己平时的操作,比如它会自动引用一些不太习惯的宏包。这种时候如果手动去修改工作量巨大。
在多次试验过后,发现最简单的方式还是将Markdown的正文部分直接粘到的文件中,因为这样至少纯公式的部分就完全不用改动。至于作用域和环境的修改就手动弄一下就好。当然这种做法仍然是不够有效,尤其手动修改的时候十分容易出错,所以我们还是总结一些常用的方法,在从Markdown转向的时候可以极大的节约我们的时间。
这个工作可能要一边做一边来完善,我们先将一些比较直接有效的方法列出,后续内容持续更新。
1.双$$
符号转\begin
-\end
型公式
方法:思路很简单,将文本全部读出,依次将双$$
改为\begin{equation}
和\end{equation}
def dollar2begin(input_fname,output_fanme):
f = open(input_fname,'r')
a = f.read()
b= ''
k = 1
for i in range(100):
if k%2 ==1:
b = a.replace("$$",r"\begin{equation}",1)
else:
b = a.replace("$$",r"\end{equation}",1)
a = b
k += 1
f2 = open(output_fanme,'w')
f2.write(b)
f2.close()
f.close()
调用方式:
input_fname = r'test_input.md'
output_fanme = r'test_output.md'
dollar2begin(input_fname,output_fanme)
2.将\matrix{}
域替换为\begin
-\end
域
方法:这个功能的实现稍嫌复杂,涉及好几个问题。首先定位\matrix
所在位置,然后定位其后的第一个左括号{
,这2步相对好实现。而最难的在于找到和左括号完全对应的右括号}
,这里则需要一定的技巧。所以这里先写出括号匹配的方法,再写出完整的替换代码。
def getIndex(s, i, targets=['{','}']):
if s[i] != targets[0]:
return -1
d = deque()
for k in range(i, len(s)):
if s[k] is targets[1]:
d.popleft()
elif s[k] is targets[0]:
d.append(s[i])
if not d:
return k
return -1
输入值:s
为原字符串,i
为第一个左括号所在的位置,targets
表示对应的左手括号。这里写成这样是为了方便其它的作用域修改。比如还可以对方括、圆括甚至于其它的一些作用域。这里实现时采用了双队列,逐步将左括加入,如果遇到右括则匹配成功删除这一对(有点像对对碰)。那么当消除到最后一对时,即找到了想要的右括。由于deque
是系统自带,因此可以不用导入相应的库。
完整的\matrix
转换方法:
def change_brackets(org_str, targname =r'\matrix',target_str = [r'\begin{matrix}',r'\end{matrix}']):
first_ind = 0
while True:
# find the sub_ind of the first bracket after targname
left_brack = org_str.find(targname,first_ind) + len(targname)
if left_brack > len(targname):
# find the corresponding right bracket
right_brack = getIndex(org_str,left_brack)
org_str = org_str[0 : left_brack : ] +' '+ org_str[left_brack + 1 : :]
org_str = org_str[0 : right_brack : ]+target_str[1]+org_str[right_brack + 1 : :]
org_str = org_str.replace(targname,target_str[0], 1)
first_ind = right_brack + 1
else:
break
return org_str
这里为了方便起见,仍然将targname
写成了默认类型,同时也对目标域的值进行了指定,所以也可以用于将其它类型进行修改。不过暂时还没发现哪些需要被修改的类型。
3.删除中不需要的Markdown关键词
这里主要指的就是\tag{0}
,这一步操作很简单,因为我们编号的时候自己会有一个编号的习惯,所以可以自行将tag
中的数值进行枚举再替换。当然最简单的就是用正则,一步到位。这里我们只写一个简单的实现方式,主要是为了写成一个统一的程序时能够方便地一步到位,而不用到处粘来粘去。
def remove_tags(org_str,targname = r'\tag'):
i = 0
first_ind = 0
while True:
# find the sub_ind of the first bracket after targname
left_brack = org_str.find(targname,first_ind) + len(targname)
if left_brack > len(targname):
# find the corresponding right bracket
right_brack = getIndex(org_str,left_brack)
org_str = org_str.replace(org_str[left_brack-len(targname):right_brack+1],'')
i += 1
print(i)
else:
break
return org_str
这里同样,虽然本意只是为了替换掉\tag{}
,但同样也可以用于其它同类型的关键词的替换。尤其这个方法可以将任意\label_name{XXX}
这种样子的东西全部删掉,可以根据自己的需要进行调整即可。
目前基本上经过上述3步操作,所有在Markdown里能够正常显示的公式就能全部在\LaTeX
中直接粘贴使用了。后续如果还有其它的发现,还会继续更新。