免责声明:这个问题是不是与……相关独立包裹。
在撰写文章时,我将内容拆分到几个文件中,以显著简化版本控制。在撰写本文时,我的大多数文章如下所示:
我的拆分文件.tex:
\documentclass{article}
\input{packages}
\input{macros}
\addbibresource{short,biblio}
\begin{document}
\input{content}
\end{document}
文件 content.tex 本身包含几个文件,包含在 \input 命令中。
写作结束后,我更喜欢保留一个文件,以便于轻松编辑、共享和备份。
感谢 bibtool,我可以轻松地从我的(巨大的).bib 文件中提取相关内容:
bibtool -x my-split-file.aux -o standalone.bib
之后,我可以将 .bib 文件的相关部分包含到我的 .tex 中,这要归功于文件内容包裹。
有没有办法对 .tex 文件执行相同操作?我想制作一份文档,其中包含以下内容:
- 用所包含文档的实际内容替换输入的命令;
- 提取用到的宏并将其他宏放在一边;
(奖励)以“明智”的方式删除注释:不是那种不加空格就能转到新行的注释(就像
I start a sentence% \footnote{I can start my footnote on a new line, for readability of the source code} and then go back to my sentence.
),而是说“这个证明可能是错误的” ;-)编辑:它可能还应该删除因删除注释而产生的空行……
我并不惧怕一些Linux脚本!
编辑:由于脚本似乎是处理该问题的最佳方法,因此我希望脚本自动运行 bibtool,提取参考书目的相关部分并将其放入文件内容环境。
编辑:如果我错了请纠正我,但我知道 5 种定义(我称之为)宏的方法:
\newcommand
\newcommand*
\renewcommand
\renewcommand*
\def
但是,我的 macros.tex 文件总是充斥着\hyphenation
和\DefineBibliographyStrings
其他 biblatex 选项,\DeclareDocumentCommand
(\NewDocumentCommand
来自解析包)、、、\DeclareMathOperator
等等\DeclareMathSymbol
。
也许 Pouya 提出的方法应该“逆转”并删除未使用的宏(用其中一种方法定义),但其余部分保持原样(而如果我理解正确的话,Pouya 只保留使用的宏)。
答案1
免责声明!
使用此产品需要您自担风险。并备份所有内容!此外,请将此视为一个起点,因为它远非完美。
我编写了一个小型 bash 脚本,它可以以相当通用的方式完成您的所有三个要求,但是,如果您根据项目结构进行个性化设置,效果会更好。
它应该与任何标准 Unix shell(包括 OS X)兼容。除此之外,你还需要乳胶膨胀它将负责内联你的文件。
在这里,我将解释脚本的每个部分如何工作以及它如何完成它的工作。虽然我建议单独使用它的各个部分(而不是作为一个整体运行)。也许,它能让你更好地控制你想要做的事情。
#!/bin/bash
# Defining some variable for you files:
# 1. The file containing all your macros
# 2. The file that the script uses to contain trimmed (i.e. only used) macros
# 3. Main .tex file
ORIGINAL_MACRO_FILE=macros_original.tex
TRIMMED_MACRO_FILE=macros_original_trimmed.tex
MAIN_FILE=paper.tex
if [[ -f macros_regex.txt || -f macros_regex_trimmed.txt || -f $TRIMMED_MACRO_FILE ]]; then
echo "Some temp files are already here. Please get rid of them first..."
exit 0
fi
# Making a trimmed version of macro files:
echo -ne '\\b(' > macros_regex.txt
echo -ne '\\b(' > macros_regex_trimmed.txt
grep -Po '(?<=\\def\\)(.+?)(?=\{)' $ORIGINAL_MACRO_FILE | tr '\n' '\|' >> macros_regex.txt
sed -i 's/.$/\)\\b/' macros_regex.txt
grep -Porh --exclude=$ORIGINAL_MACRO_FILE $(cat ./macros_regex.txt) *.tex | sort | uniq | tr '\n' '\|' >> macros_regex_trimmed.txt
sed -i 's/.$/\)\\b/' macros_regex_trimmed.txt
grep -P $(cat ./macros_regex_trimmed.txt) $ORIGINAL_MACRO_FILE > $TRIMMED_MACRO_FILE
# Backing up the original macro file:
cp $ORIGINAL_MACRO_FILE $ORIGINAL_MACRO_FILE\_backup
mv $TRIMMED_MACRO_FILE $ORIGINAL_MACRO_FILE
# Inline the file to collect have one big file. This is needed for finding unused macros
perl latexpand --keep-comments $MAIN_FILE > inlined_paper.tex
rm macros_regex.txt macros_regex_trimmed.txt
# Putting back the original macro files:
rm $ORIGINAL_MACRO_FILE
mv $ORIGINAL_MACRO_FILE\_backup $ORIGINAL_MACRO_FILE
# Removing comments
sed -ri '/\%[^\n].+/ d' inlined_paper.tex
# Removing blank lines if you want
sed -ie '/^$/ d' inlined_paper.tex
它需要两个文件才能启动:
ORIGINAL_MACRO_FILE=macros_original.tex
MAIN_FILE=paper.tex
包含所有宏和主文件的文件tex
。TRIMMED_MACRO_FILE
是一个临时文件,用于保存所用宏的列表。然后检查此临时文件以及另外两个文本文件是否存在,如果不存在,则继续(请注意,脚本完成后将删除这些辅助文件)。
它首先解决了你的第二个问题!它使用这个正则表达式在你的宏文件中进行搜索(?<=\\def\\)(.+?)(?=\{)
,并收集姓名所有宏。在我的示例中,我假设宏的形式为\def\name{...
,但是,如果您使用其他宏定义命令,则以下是一些正则表达式:
(?<=\\newcommand\{\\)(.+?)(?=\})
为了新命令(?<=\\renewcommand\{\\)(.+?)(?=\})
为了更新命令(?<=\\newcommand\*\{\\)(.+?)(?=\})
为了新命令*
您可以在正则表达式中使用逻辑运算符or
( )来获得多个上述定义,例如|
((?<=\\def\\)|(?<=\\renewcommand\{\\))(.+?)(?=\{)
使用def
和renewcommand
语法。
macros_regex.txt
然后它以以下形式存储所有宏名称:
\b(amacro|anothermacro|foo|bar|etc)\b
然后使用下一行,检查已使用以下哪一个宏:
grep -Porh --exclude=$ORIGINAL_MACRO_FILE $(cat ./macros_regex.txt) *.tex | sort | uniq | tr '\n' '\|' >> macros_regex_trimmed.txt
事情是这样的:grep -Porh
意味着使用 perl-regex 在文件内容中搜索,仅打印匹配的行,递归并省略文件名。它还排除了您的原始宏文件,因为它显然会与所有模式匹配。最后,我们提供我们之前创建的模式,$(cat ./macros_regex.txt)
然后在所有tex
文件中进行递归搜索。
然后对结果进行排序,并删除重复项(分别通过管道连接到sort
和uniq
)。然后,我们再次以以下形式创建此输出的正则表达式
\b(anothermacro|foo|etc)\b
但这次它只包含使用过的宏。最后,grep
此文件包含原始宏文件并将数据保存在 中TRIMMED_MACRO_FILE
。总结一下,如果我们有一个以下形式的文件:
% original macros
\def\bfa{{\mbox{\boldmath $a$}}}
\def\bfb{{\mbox{\boldmath $b$}}}
\def\bfc{{\mbox{\boldmath $c$}}}
\def\bfd{{\mbox{\boldmath $d$}}}
\def\bfe{{\mbox{\boldmath $e$}}}
\def\bff{{\mbox{\boldmath $f$}}}
经过这一阶段,我们有:
% trimmed macro file
\def\bfb{{\mbox{\boldmath $b$}}}
\def\bfc{{\mbox{\boldmath $c$}}}
\def\bff{{\mbox{\boldmath $f$}}}
这是您的项目中使用的宏的定义。
现在,我在这里解释一下为什么我首先解决了你的第二个问题:D
。这个想法是,一旦我们有了文件的修剪版本,就交换原始宏文件和修剪后的宏文件,然后扩展/内联所有内容。这是通过备份原始宏文件、重命名修剪后的文件并最终用于内联latexpand
所有内容来完成的。
perl latexpand --keep-comments $MAIN_FILE > inlined_paper.tex
latexpand
是一个处理\input
和的perl 程序\include
。如您所见,我已使用标志--keep-comments
来保留注释。如果您不这样做,它将很好地清除所有注释,但是,此清除包括您提到的需要保留的注释。清除注释是一个简单的sed
单行命令,将\%[^\n].+
模式替换为空白。该正则表达式表示百分号后面不是直接跟换行符,而是跟一个或多个任何类型的字符。最后,如果您想删除空行,可以使用最后一个命令,即sed -ie '/^$/ d' inlined_paper.tex
或以其他方式对其进行注释。
如您所见,这是一个可以完成工作的脚本,但它应该根据您的项目结构和命令进行定制。再次,我建议单独使用此代码的不同部分,而不是将其作为一个整体运行。例如,删除注释的行是一个有用的单行独立代码。
最后,我建议坚持使用它,latexpand
因为它是为此目的而设计的专业工具,而不是我创建的这个脚本,因为我的其他代码未编译(这说明了很多问题!)我感到无聊。
cp
PS 我假设读者对基本的 bash 命令(例如、mv
和)相当熟悉grep
。如果您发现此答案不够详细,请发表评论。