我喜欢用它texcount
来计算 LaTeX 文档中的单词数,我想知道它是否可以给我一些比默认信息更精确的信息。
在我写的这个作业中,给定标题(表格或图形上)中的单词不算数,除了如果里面有超过 50 个单词。事实上,texcount
它只给我全部的标题和脚注中的字数,所以我想知道是否可以编写一些代码来获得更详细的输出:
- 是否可以获取每个标题的字数列表?至少,这样我就能知道应该将哪些添加到我的字数中。或者更好的是,
- 是否可以
texcount
仅记录超过阈值(例如 50 个字)的标题的字数?
在大多数情况下,默认行为对我来说是可以接受的,因为如果总数otherwords
足够低,我知道我没问题。尽管如此,我想借此机会更好地了解texcount
工作原理。
答案1
这不是一个正确的答案,而不仅仅是一个评论。
正如 Marijn 在他的回答中已经指出的那样,TeXcount 会逐个将单词添加到计数中:即,它不会以递归方式分析文本,一次分析一个块/组/参数,然后将其添加到包含它的块/组/参数中。因此,在将其添加到总数时,它不知道每个块中有多少个单词,这使得按大小进行过滤变得困难。Marijn 的解决方案是一种黑客行为,但最简单的解决方案可能就是这样。
另一种方法是保存标题开头的字数,然后在标题结尾处检查是否应保留该字数或将字数恢复到开头的字数。我会看看是否能想出一个可行的办法……但这个想法不太对劲。
至于列出每个标题的字数,我想不出任何好的解决方案,但这次又有一个不需要更改脚本的 hack。它涉及将 \caption 定义为开始新子计数的断点:用于 \section 类似的宏。文档恰好在使用上不正确,但将其添加到文档顶部某处应该可以正常工作:
%TC:breakmacro \caption Caption
由此产生的输出不会很漂亮,因为它本质上会使用标题作为新子计数的标题。但是,标题单词现在将被视为“文本外的单词”。为了避免其他“文本外的单词”被添加到此问题,您可能需要将标题指定为单独的计数器,使其成为完整的指令集:
%TC:breakmacro \caption Caption
%TC:newcounter caption Caption text
%TC:macro \caption [caption]
%TC:floatinclude \caption [caption]
请注意,floatinclude
类似于macro
,但在浮动环境内指定宏处理规则。
答案2
以下是一个概念验证,用于有条件地计算宏参数中的单词数,在本例中为\caption
。它需要修改 的源代码texcount
,该源代码是用 Perl 编写的。
有一个子程序inc_count
(texcount
3.1.1 中的第 2800 行左右)逐个计数单词。实际增加计数的行是
${$count->{'counts'}}[$cnt]+=$value;
变量$cnt
代表计数类型。标题为类型 3。
您可以向此函数添加一些检查,以便仅当标题中的单词总数达到预定义的阈值时才对标题单词进行计数。为此,您需要使用一个变量来跟踪标题中当前的单词总数,并使用另一个变量来跟踪前一个单词的类型。检查需要考虑的可能情况包括:
- 该类型不是标题。然后,重置标题字数并按其类型正常计数字数。
- 可选地,检查前一个单词是否在标题中,如果是,则该标题现已结束,并且可以打印单词数。
- 类型是标题。然后检查前一个单词是否也是标题。
- 如果没有,则表示新字幕已开始。将临时计数设为 1,暂时不存储计数。
- 如果前一个单词是标题,则检查是否已达到阈值。
- 如果不是,则增加计数,但不要存储计数。
- 如果计数达到阈值,则存储当前计数。
- 如果计数超过阈值,则存储额外的计数一。
梅威瑟:
my $prev_type;
my $capt_count;
# Increment TeX count for a given count type
sub inc_count {
my ($tex,$cnt,$value)=@_;
my $count=$tex->{'subcount'};
if (!defined $value) {$value=1;}
if (!defined $prev_type) {$prev_type = -1;}
if (!defined $capt_count) {$capt_count = 0;}
my $CAPT_THRESHOLD = 3;
if ($cnt != 3){ # not a caption, reset and count as normal
if($prev_type == 3){ # previous word in caption, which has now ended
print "Caption: $capt_count words\n";
}
$capt_count = 0; # reset
$prev_type = $cnt;
${$count->{'counts'}}[$cnt]+=$value; # count as normal
}else{ # in a caption
if ($prev_type == 3) { # check if previous word was also in a caption
$capt_count++;
if ($capt_count == $CAPT_THRESHOLD) { # at threshold
${$count->{'counts'}}[$cnt]+=$capt_count; # count previously ignored words
}
if ($capt_count > $CAPT_THRESHOLD) { # over threshold
${$count->{'counts'}}[$cnt]+=$value; # count one for current word
}
} else { # previous was not a caption, so start of new caption
$prev_type = 3;
$capt_count = 1;
}
}
}
LaTeX 文档:
\documentclass{article}
\begin{document}
Some normal text
\begin{figure}
text in figure
\caption{short caption}
\end{figure}
\begin{figure}
text in figure
\caption{one two three four five}
\end{figure}
more text
\end{document}
texcount
输出(阈值 = 3,因此第一个字幕不计算在内,但第二个字幕计算在内):
Caption: 2 words
Caption: 5 words
File: captioncount.tex
Encoding: ascii
Words in text: 5
Words in headers: 0
Words outside text (captions, etc.): 5
Number of headers: 0
Number of floats/tables/figures: 2
Number of math inlines: 0
Number of math displayed: 0
请注意,添加的 Perl 代码不是很干净或不符合最佳实践,并且可能会产生不正确的结果 - 它只是一个概念证明。