用于确定括号术语有效性的命令行工具

用于确定括号术语有效性的命令行工具

我正在寻找一个可以自动检查 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 中用于比较运算符,并且其中一些字符在注释中被发现不匹配或被转义。

相关内容