You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash实现Pandoc风格Markdown引用转LaTeX格式引用

Markdown转LaTeX引用格式转换脚本修复方案

问题分析

你当前的脚本核心问题出在全局条件判断逻辑:脚本是对整个文件做全局匹配判断,而非针对每个[@...]引用块单独处理。比如文件中同时存在带页码的单个引用和多引用时,脚本只会执行第一个匹配的if分支,导致部分引用格式转换不完整。此外,判断条件的正则也存在覆盖不全的问题。

修复思路

放弃全局if判断,改为按引用块类型顺序处理:先处理复杂的多引用场景,再处理单个引用场景,确保每个引用块都被正确转换。

方案1:改进版Shell脚本(sed+awk组合)

这个方案先用sed拆分引用块,再用awk处理块内的每个引用项,最后收尾处理单个引用:

#!/bin/bash
input_file="$1"
temp_file="${input_file%.md}_temp.md"

# 第一步:处理多引用块(包含;的[@...])
sed -E 's/\[@([^]]+)\]/\n&\n/g' "$input_file" | awk '
/^\[@.*\]$/ {
    # 移除首尾的[@和]
    sub(/^\[@/, "", $0)
    sub(/\]$/, "", $0)
    # 按;分割每个引用项
    n = split($0, cites, /; /)
    printf "\\footnote{"
    for (i=1; i<=n; i++) {
        if (cites[i] ~ /, [0-9]+$/) {
            # 处理带页码的引用项
            split(cites[i], parts, /, /)
            printf "\\cite[%s]{%s}", parts[2], substr(parts[1], 2)
        } else {
            # 处理不带页码的引用项
            printf "\\cite[]{%s}", substr(cites[i], 2)
        }
        if (i < n) printf ", "
    }
    printf "}\n"
    next
}
1' > "$temp_file"

# 第二步:处理单个带页码的引用
sed -i -E 's/\[@([^,]+), ([0-9]+)\]/\\footcite[\2]{\1}/g' "$temp_file"

# 第三步:处理单个不带页码的引用
sed -i -E 's/\[@([^]]+)\]/\\footcite{\1}/g' "$temp_file"

# 替换原文件(可选,根据需求调整)
mv "$temp_file" "$input_file"

方案2:简洁的Perl单命令(推荐)

Perl的正则支持复杂分组和动态替换,一行命令即可覆盖所有场景:

perl -0pe '
# 处理多引用块
s/\[@(.*?)\]/do {
    my $c = $1;
    $c =~ s/; /, /g;
    $c =~ s/@([^,]+)(, (\d+))?/\\cite[$3]{$1}/g;
    $c =~ s/\[\]/\[\\]/g; # 修复无页码的空括号格式
    "\\footnote{$c}"
}/ge;
# 处理单个带页码的引用
s/\[@([^,]+), (\d+)\]/\\footcite[$2]{$1}/g;
# 处理单个不带页码的引用
s/\[@([^]]+)\]/\\footcite{$1}/g;
' "$input_file" > "$input_file_temp.md"

脚本说明

  1. 多引用优先处理:多引用结构包含单个引用的特征,先处理可避免被后续单个引用规则误匹配。
  2. 分层转换逻辑:先拆分多引用块内的子项,分别处理带/不带页码的情况,再重组为LaTeX的\footnote{\cite...}格式。
  3. 单个引用收尾:处理剩余的单个引用,区分带页码和不带页码两种场景。

内容的提问来源于stack exchange,提问作者ReaderGuy42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:35:04