Latex-bibitem自动引用,自动排序,多文件支持的bibitem自动化脚本

最近写毕业论文,用了Latex,然后就是用了bibtex作为文献管理,太折磨了,中国知网居然不能直接导出bibtex格式ANDbitex编译也太慢了吧!!!,于是我就想用bibitem,下面写了个py的脚本,奉献给被bibtex折磨疯的小伙伴。Python脚本自动排序\begin{thebibliography}引用自动排序脚本。

 功能概述
1. 智能引用检测:递归扫描主文档及所有`\input`子文件
2. 自动排序:按实际引用顺序重排文献条目
3. 未引用标注:将未引用的文献条目转为注释,同时注释掉的被引用也能恢复
4. 安全备份:自动生成`.bak`备份文件
5. 编码支持:强制UTF-8编码处理,自己改改也能兼容其他。

配置修改
用文本编辑器打开脚本,修改这行:
processor = UTF8ReferenceProcessor(main_file="tutorial.tex") # 修改为你的主tex文件路径

把脚本和主tex文件放一个目录, 然后运行脚本就可以了,完事了,就是这么简单。

上代码

好了废话不多说,直接上代码!

import re
import os
import shutil
from collections import OrderedDict
#desinged by TangJianfu-2025.3

class UTF8ReferenceProcessor:
    def __init__(self, main_file):
        self.root_dir = os.path.dirname(main_file)
        self.main_file = main_file
        self.citation_order = OrderedDict()
        self.bib_file = None
        self.processed_files = set()

    def resolve_path(self, input_path):
        """解析LaTeX输入路径"""
        base_path = re.sub(r'\.tex$', '', input_path, flags=re.IGNORECASE)
        for ext in ['', '.tex']:
            full_path = os.path.normpath(os.path.join(self.root_dir, f"{base_path}{ext}"))
            if os.path.exists(full_path):
                return full_path
        raise FileNotFoundError(f"文件未找到: {input_path}")

    def parse_structure(self, file_path):
        """递归解析文档结构"""
        if file_path in self.processed_files:
            return
        self.processed_files.add(file_path)

        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                lines = f.readlines()  # 改为逐行读取
        except UnicodeDecodeError as e:
            raise ValueError(f"UTF-8解码失败: {file_path}") from e

 
        # 捕获参考文献文件路径
        if not self.bib_file:
            for line in lines:
                #通过判断begin{thebibliography}识别参考文献所在文件目录
                match = re.search(r'\\begin{(.*?thebibliography*?)}', line, re.IGNORECASE)
                if match:
                    self.bib_file = file_path
                    break

        # 收集所有引用(新增逐行处理)
        for line_num, line in enumerate(lines, 1):
            # 注释检查,注释则跳过
            if line.strip().startswith(('%', '%%')):#判断注释
                continue

            #寻找这行中的input,并递归处理input(保持原有逻辑)
            content = ''.join(line)
            for match in re.finditer(r'\\input{(.+?)}', line):
                child_path = self.resolve_path(match.group(1))
                self.parse_structure(child_path)

            #寻找这行中的引用
            for match in re.finditer(r'\\(?:cite[ptss]*|citess){([^}]+)}', line):
                # 收集引用
                for key in match.group(1).split(','):
                    clean_key = key.strip()
                    if clean_key and clean_key not in self.citation_order:
                        self.citation_order[clean_key] = None
    def replace_between(self,bib_content, firstPos, finPos, newstr):
        # 查找起始索引
        start_index = bib_content.find(firstPos)
        if start_index == -1:
            return bib_content  # firstPos未找到,返回原字符串或抛出异常
        
        # 在start_index之后查找finPos的起始索引
        end_index = bib_content.rfind(finPos, start_index)
        if end_index == -1:
            return bib_content  # finPos未找到,返回原字符串或抛出异常
        
        # 计算finPos的结束位置
        end_index_end = end_index + len(finPos)
        
        # 拼接新字符串
        return bib_content[:start_index].strip('\n') + newstr + bib_content[end_index_end:].strip('\n')

    def process_bibliography(self):
        """处理参考文献排序"""
        if not self.bib_file:
            raise ValueError("未检测到参考文献文件")

        # 读取文献内容
        try:
            with open(self.bib_file, 'r', encoding='utf-8') as f:
                bib_content = f.read()
        except UnicodeDecodeError as e:
            raise ValueError(f"参考文献文件非UTF-8编码: {self.bib_file}") from e

        # 提取文献条目
        entries = {}
        item_pattern = re.compile(
            r'(\\bibitem{([^}]+)}.*?)(?=\\bibitem{|\\end{thebibliography}|$)',
            re.DOTALL
        )
        for match in item_pattern.finditer(bib_content):
            entries[match.group(2)] = match.group(1).strip().strip('%').strip('\n').replace('\n%','\n')

        # 生成排序后的内容
        #被引用了的条目(排序后)
        sorted_items = [entries[key] for key in self.citation_order if key in entries]
        #未使用的条目
        unused_items = [f"%{modified_entry}" for key, entry in entries.items()  if key not in self.citation_order  for modified_entry in [entry.replace('\n', '\n%')]] 

        firstPos= entries[list(entries.keys())[0]]#第一个bititem
        finPos=entries[list(entries.keys())[-1]]#最后一个bititem
        
        new_content= self.replace_between(bib_content, firstPos, finPos, "\n\n"+'\n\n'.join(sorted_items+unused_items)+'\n\n')

        # 安全写入(保留备份)
        backup_path = f"{self.bib_file}.bak"
        shutil.copyfile(self.bib_file, backup_path)
        with open(self.bib_file, 'w', encoding='utf-8') as f:
            f.write(new_content)

    def execute(self):
        """执行入口"""
        self.parse_structure(self.main_file)
        self.process_bibliography()
        print(f"文献排序处理完成!已引用 {len(self.citation_order)} 篇文献;\n已经覆写文件{self.bib_file},原始文件备份于{self.bib_file}.bak")

if __name__ == "__main__":
    processor = UTF8ReferenceProcessor(main_file="tutorial.tex")#主latex文件地址
    processor.execute()#执行代码

这就完了?当然是实现自动一体化,如果你用的是vscode,在配置文件里修改。

"latex-workshop.latex.tools"里添加脚本:

然后配置在latex编译前,先运行脚本,配置"latex-workshop.latex.recipes"。

大功成告!后面就正常编译latex就可以啦,再也不用担心任何的排版引用和手动运行问题啦!

下面是AI生成的,随便看看,溜了溜了!! 

🔍 工作原理
1. **文件解析**
    - 通过正则表达式匹配`\cite`系列命令
    - 支持`\input`嵌套文件的递归解析
    - 自动跳过注释内容(以%开头的行)

2. **文献处理**
    - 识别`thebibliography`环境位置
    - 按首次引用顺序重排`\bibitem`
    - 未引用条目添加`%`注释符

3. **安全机制**
    - 自动创建`.bak`备份文件
    - UTF-8编码强制校验

 ⚠️ 注意事项
1. **编码规范**
    - 确保所有tex文件均为**UTF-8无BOM**格式
    - 常见乱码问题解决方法:
    ```python
    # 在VSCode中可通过"编码保存"功能转换
    File -> Save with Encoding -> UTF-8

2. **文献规范**
    - 仅支持原生`thebibliography`环境
    - 如需处理`.bib`文件请使用BibTeX

3. **路径识别**
    - 主文件路径需使用`/`或双反斜杠`\\`
    - 示例:`main_file="D:/论文/正文.tex"`

 📂 文件结构建议
```
论文项目/
├── 主文件.tex
├── chapters/
│   ├── 引言.tex
│   └── 实验.tex
└── 文献排序.py
```

💡 高级技巧
- **批量处理**:创建bat脚本实现一键运行
```bat
@echo off
python 文献排序.py
pause
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值