找回密码
 快速注册
搜索
查看: 31|回复: 5

定理、命题、例题等等的编号问题

[复制链接]

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

abababa 发表于 2025-1-21 16:51 |阅读模式
以前问过一次:kuing.cjhb.site/forum.php?mod=viewthread&tid=4466
现在我是这么想的,能不能在打字的时候,编号就直接编成年月日时分秒这种格式,秒太短了可能用不上,就年月日时分这种,比如一个定理编号为thm:202501211643,然后这时可能整个文档没打完,但是已经可以编译了,就编译一下,但是在编译前,按这个定理出现的顺序,把那个编号统一改过来,比如这是第2章第一节出现的第3个定理,在编译前就把thm:202501211643替换成thm:02:01:03这种,连引用的地方也统一替换。
然后下次可能又加入了新的定理,新定理还是用thm:202501211646这种方式编号,在编译时也像前面那样替换。
最后一个是可能在编号为thm:02:01:03的定理前面插入一条新定理,这时新定理的编号应该是thm:02:01:03,原来的thm:02:01:03自动变成thm:02:01:04,连同引用的地方都一起被替换。

我就是想能不能在编译前运行一个什么脚本之类的,完成上面那些东西,这样在.tex文件里的编号就和.pdf显示的编号一致了。

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

 楼主| abababa 发表于 2025-1-26 18:35
忽然想到这个是不是能用那个python来做?具体的我不会写,但是有个大致的思路。
首先我的tex都是01.01.tex,02.03.tex这样的名字,这两个分别表示第一章第一节和第二章第三节。然后我想的是,在m.n.tex文件里出现的theorem,那编号肯定是\label{thm:m:n:x}这样的,其中x就表示这个定理在这个文件里是第几个。那这样的话,能不能查找这个文件里的所有\begin{theorem},然后计数,就能依次给那些定理编号了,把这种编号叫做“好编号”。

其次是把那些定理都加上好编号,这分两种情况,第一种是这个定理本身没有编号过,那直接加上就行了,没编号的定理在后面也不会被引用。第二种是这个定理已经编号过了,比如\begin{theorem}\label{thm:202501261823}这种(把这种编号叫“坏编号”),这时要弄一个像双射似的东西,把坏编号和好编号对应起来,然后用好编号替换坏编号,并且在其它的文件里出现引用的地方也替换过来。

再次是有的定理已经有好编号了,比如\begin{theorem}\label{thm:02:03:04},但是后来在这个定理之前又加入了一个新的定理,新的定理还没编号过。这时也按第一步把定理的好编号都找出来,但是已经有好编号的,因为现在顺序错了,现在也都视为坏编号,然后用好编号替换坏编号。但是替换其它文件里的引用时,应该按从大到小的次序替换,例如
\begin{theorem}\label{thm:02:03:04}
\begin{theorem}\label{thm:02:03:05}

\autoref{thm:02:03:04}
\autoref{thm:02:03:05}

如果在定理thm:02:03:04之前加入一个新定理,新的编号应该是
\begin{theorem}\label{thm:02:03:05}
\begin{theorem}\label{thm:02:03:06}

如果是先替换编号小的定理,那就把\autoref{thm:02:03:04}换成\autoref{thm:02:03:05}了,下一步替换\autoref{thm:02:03:05},现在就有两个\autoref{thm:02:03:05},都会被替换成\autoref{thm:02:03:06},这就不对了。而从编号大的定理替换,会先把\autoref{thm:02:03:05}换成\autoref{thm:02:03:06},这时\autoref{thm:02:03:05}就空下了,再把\autoref{thm:02:03:04}换成\autoref{thm:02:03:05}就没问题。

暂时想到这么多。

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

 楼主| abababa 发表于 2025-2-22 12:17
abababa 发表于 2025-1-26 18:35
忽然想到这个是不是能用那个python来做?具体的我不会写,但是有个大致的思路。
首先我的tex都是01.01.tex ...

下面的是maven网友根据我的需要写的python代码,我在自己的tex里运行了一下,目前没发现什么问题。
  1. # tex 文档必须在同一目录中,并且文档名必须是 c.s.tex 格式,其中 c,s 都是补前导零的两位数字,例如 01.02.tex
  2. # tex 文档中,环境起始和标签必须在同一行,例如 \begin{theorem}[Cauchy]\label{thm:01}
  3. # 用法:复制本文件到 tex 文档所在目录,在终端跳转到此目录,并运行 python3 auto_label.py,将备份被修改的文档并为这些文档加标签
  4. import os, re, uuid
  5. from collections import OrderedDict
  6. from datetime import datetime
  7. import shutil
  8. def process_file(text, chapter, section, env_name, env_short_name):
  9.         """
  10.         处理单个文本,将指定环境都添加标签,并生成新旧标签的对应字典。
  11.         :param text: 被处理的文本
  12.         :param chapter: 章号,例如 01
  13.         :param section: 节号,例如 02
  14.         :param env_name: 环境名,例如 theorem
  15.         :param env_short_name: 环境短名,例如 thm,用于标签前缀
  16.         :return: 返回二元数组,第 0 个元素是将指定环境都添加标签后的文本,第 1 个元素是此文本中所有标签的新旧名对应字典。
  17.         """
  18.         pattern = re.compile(fr'\\begin{{{env_name}}}(\[.*?\])*(.*)')
  19.         # 将文本中的环境全部增加 label 后的新文本。已有 label 不变,缺失 label 由 uuid 生成
  20.         new_tex = ''
  21.         # pdf 中可见的 label
  22.         label_number = 0
  23.         # 原 label 和 可见 label 的对应字典
  24.         label_dict = OrderedDict({})
  25.         for line_num, line in enumerate(text.splitlines(), start=1):
  26.                 result = re.match(pattern, line)
  27.                 # 匹配到环境起始行
  28.                 if result:
  29.                         label_number += 1
  30.                         new_line = f'\\begin{{{env_name}}}'
  31.                         if result.group(1) != None:
  32.                                 new_line += str(result.group(1))
  33.                         env_label = str(result.group(2))
  34.                         old_label = uuid.uuid4().hex
  35.                         if env_label != '':
  36.                                 old_label = re.match(r'\\label\{(.*)\}', env_label).group(1)
  37.                         new_line += f'\\label{{{old_label}}}'
  38.                         new_tex += new_line+'\n'
  39.                         new_label = f"{env_short_name}:{chapter}:{section}:{str(label_number).zfill(2)}"
  40.                         label_dict[old_label] = new_label
  41.                 # 非环境起始行,直接追加
  42.                 else:
  43.                         new_tex += line+'\n'
  44.         # 字典逆序,替换时从 可见 label 的最大编号开始替换
  45.         label_dict = OrderedDict(reversed(label_dict.items()))
  46.         return [new_tex, label_dict]
  47. # 所有要处理的 tex 文档的环境标签字典。复数加 s,这就叫懂英文
  48. label_dicts = OrderedDict({})
  49. # 需要更新 label 的环境名和短名
  50. envs = [['definition', 'def'], ['theorem', 'thm'], ['proposition', 'ps']]
  51. # 待写入的文件键值对(文件名:新文本内容)
  52. new_files = {}
  53. # 处理所有 m.n.tex 文件,将文件名与新文本内容对应
  54. for fname in os.listdir('.'):
  55.         if match := re.fullmatch(r'(\d{2})\.(\d{2})\.tex', fname):
  56.                 chapter, section = match.groups()
  57.                 with open(fname, 'r', encoding='utf-8') as f:
  58.                         text = f.read()
  59.                 for env in envs:
  60.                         text, label_dict = process_file(text, str(chapter), str(section), env[0], env[1])
  61.                         label_dicts.update(label_dict)
  62.                 new_files[fname] = text
  63. # 备份文件目录
  64. timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
  65. bak_dir = f'bak{timestamp}'
  66. os.makedirs(bak_dir, exist_ok=True)
  67. # 替换 label,备份并重新写入 tex 文件
  68. for fname, text in new_files.items():
  69.         shutil.copy(fname, bak_dir)
  70.         for old_label, label in label_dicts.items():
  71.                 text = text.replace(old_label, label)
  72.         with open(fname, 'w', encoding='utf-8') as f:
  73.                 f.write(text)
复制代码

3

主题

452

回帖

6188

积分

积分
6188
QQ

显示全部楼层

爪机专用 发表于 2025-2-22 12:19
还真能整出来吗😀
I am majia of kuing

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

 楼主| abababa 发表于 2025-2-22 12:40
本帖最后由 abababa 于 2025-2-22 12:52 编辑
爪机专用 发表于 2025-2-22 12:19
还真能整出来吗😀


可能是他的编号格式和我的不一样,他写的那个说是没测试过,所以加了备份功能,要是出错了可以恢复回来。

我试了两次,分别是我以前学泛函分析和抽象代数时打的latex文档,主要的是有一些定理我觉得有用,但是书上没有这个定理,我就把这个定理加进某一节里了,但加进去的位置并不是最后,比如原来定理是1到6,新加入的定理加到了3后面,那这样的话,要是把新加入的定理编号成4,原来的定理4,5,6的编号都要变,连带着后面的引用也要变,所以这个新定理我就没按原来的顺序编号,写了一堆字母abcaa之类的放在那,可是现在pdf里显示的定理5,其实是原来的定理4,都弄混了,以后想引用时就容易弄错,所以就一直想有这个能自动编号的

413

主题

1558

回帖

1万

积分

积分
11498

显示全部楼层

 楼主| abababa 发表于 2025-2-23 12:16
abababa 发表于 2025-2-22 12:17
下面的是maven网友根据我的需要写的python代码,我在自己的tex里运行了一下,目前没发现什么问题。
...

$type 测试.zip (2.55 KB, 下载次数: 0)
一些测试用的tex文件。原始的文件里,label有一些和pdf里显示的不一致。运行那个auto_label.py之后,label都变得一致了。生成了一个备份文件夹,把原始的文件备份了一下。可以用Meld这个软件来对比两个文件的差异,把备份的文件和修改后的文件对比,查看改了哪些地方。
Meld软件下载网站:meldmerge.org/

手机版|悠闲数学娱乐论坛(第3版)

GMT+8, 2025-3-4 07:12

Powered by Discuz!

× 快速回复 返回顶部 返回列表