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"
脚本说明
- 多引用优先处理:多引用结构包含单个引用的特征,先处理可避免被后续单个引用规则误匹配。
- 分层转换逻辑:先拆分多引用块内的子项,分别处理带/不带页码的情况,再重组为LaTeX的
\footnote{\cite...}格式。 - 单个引用收尾:处理剩余的单个引用,区分带页码和不带页码两种场景。
内容的提问来源于stack exchange,提问作者ReaderGuy42
相关产品推荐
相关产品推荐

