我正在寻找一个可以自动检查 LaTeX 文档是否是正确的括号术语的工具。
编写这样一个工具非常容易,但在编写之前,我想知道是否已经存在一个工具。
它需要是命令行工具或 shell 代码,以便我可以在脚本中使用它。 GUI 工具对我没有帮助。它需要检查括号() {} [] <>
。
我将文档视为括号表达式。所有非括号字符都不重要。对于只有一种类型的括号的括号项 T 来说,它需要满足以下条件:
- T 中左括号和右括号的数量必须相等。
- T 的前缀中不能包含比左括号更多的右括号。
如果有多种类型的括号(括号的集合B),则对于所有β ∈ B,T必须满足上述条件,并且由配对括号导出的T的所有子串也必须满足上述条件。 T 的子串 (t_1, ..., t_s) 被认为是由 β 类型的配对括号引出 iff (β_opening, t_1, ..., t_s, β_ opening) 是 T 的子串。
答案1
我不知道有哪个程序只会检查括号的正确配对,而不会因为其他不相关的语法错误而烦扰您,具体取决于这些检查器所针对的语言。
正如您所说,编写这样的工具很容易,因此这里有一个小脚本,希望能够完成这项工作:
#!/bin/sh
# If a file is given as 1st parameter, use it, else use stdin
[ "$#" -gt 0 ] && exec < "$1"
# A correct input file should result in an empty string
tr -d -c '{}[]()<>' |
sed '
# Eliminate adjacent bracket pairs one by one
:loop
s/\[\]\|()\|{}\|<>//g
t loop
' |
if grep -q .; then
echo "ERROR: unpaired brackets!"
else
echo "OK: all brackets are paired."
fi
如果您的sed
实现不支持(非标准)\|
交替运算符,您可以将该s
命令替换为 4:
s/\[\]//g
s/{}//g
s/()//g
s/<>//g
上面的命令tr
是标准的,但有些(基于 SysV 的命令)会抱怨这样的未转义[
不包含范围。有了这些,您可以[
使用\
( tr -cd '{}()<>\[]'
) 转义,但随后它会根据 POSIX 变得未指定,并且有些无法删除退格字符。为了可移植性,在基于 ASCII 的系统上,您可以使用tr -cd '{}()<>\133\135'
.
答案2
grep
使用支持 PCRE 的GNU ,您可以执行以下操作:
find . -size +0 -type f -exec \
grep -zLP '\A((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*+)\z' {} +
找到这样的文件(假设它们不包含 NUL 字节,并且每个文件都足够小以适合整个内存)。
或者直接调用perl
(允许带NUL字节的文件):
find . -size +0 -type f -exec perl -l -0777 -ne 'print $ARGV unless
/^((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*)$/' {} +
一些 perl/PCRE 特定的运算符:
\A
和\z
分别在主题的开头和结尾匹配。类似于^
and$
(或带有-x
选项),但当主语是多行时没有歧义(在某些版本的 GNU 中需要grep
)。++
和是和运算符*+
的非回溯版本。当我们知道它无法找到匹配项时,这可以帮助正则表达式引擎不要太努力地寻找匹配项。+
*
(?1)
指相应捕获组中的正则表达式。这允许递归正则表达式。(?:...)
,与相同(...)
但仅用于分组(不捕获...)
*.tex
请注意,它在我的系统上发现很大比例的文件,因为<
/>
在 TeX 中用于比较运算符,并且其中一些字符在注释中被发现不匹配或被转义。