Ferramenta de linha de comando para determinar a validade do termo entre colchetes

1

Estou procurando uma ferramenta que verifique automaticamente se um documento LaTeX é um termo de colchete correto.

É muito fácil escrever tal ferramenta, mas antes disso, quero saber se já existe uma.

Ele precisa ser uma ferramenta de linha de comando ou código shell para que eu possa usá-lo em um script. Uma ferramenta GUI não me ajudará. Ele precisa verificar os colchetes () {} [] <> .

Eu vejo o documento como uma expressão de colchetes. Todos os caracteres sem colchetes não importam. Para um termo de colchete T com apenas 1 tipo de colchete para ser válido, ele precisa atender a essas condições:

  • O número de chaves de abertura e fechamento em T deve ser igual.
  • Não deve haver nenhum prefixo de T que contenha mais fechamento do que colchetes de abertura.

Se houver vários tipos de parênteses (um conjunto B de parênteses), T deve atender às condições acima mencionadas para todo β ∈ B e todas as substrings de T induzidas por parêntesis em pares devem atender às condições mencionadas acima. Uma substring (t_1, ..., t_s) de T é dita ser induzida por parêntesis pareados do tipo β iff (β_opening, t_1, ..., t_s, β_closing) é uma substring de T.

    
por UTF-8 01.10.2017 / 00:33

2 respostas

3

Com o GNU grep construído com suporte a PCRE, você poderia:

find . -size +0 -type f -exec \
  grep -zLP '\A((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*+)\z' {} +

Para encontrar esses arquivos (supondo que eles não contenham bytes NUL e que cada um seja pequeno o suficiente para caber todo na memória).

Ou chame perl diretamente (permitindo arquivos com bytes NUL):

find . -size +0 -type f -exec perl -l -0777 -ne 'print $ARGV unless
  /^((?:[^][<>{()}]++|<(?1)>|\{(?1)\}|\[(?1)\]|\((?1)\))*)$/' {} +

Alguns operadores específicos de perl / PCRE:

  • \A e \z correspondem respectivamente no início e no final do assunto. Como ^ e $ (ou com a opção -x ), mas sem ambigüidade quando o assunto é multilinha (necessário em algumas versões do GNU grep ).
  • ++ e *+ são as versões sem retrocesso dos operadores + e * . Aqui, o mecanismo de regexp não ajuda muito a encontrar uma correspondência quando sabemos que não é possível.
  • (?1) refere-se ao regexp no grupo de captura correspondente. Isso permite regexps recursivos.
  • (?:...) , o mesmo que (...) , mas apenas para agrupamento (sem captura ...)

Note que ele encontra grandes proporções dos arquivos *.tex no meu sistema, pois < / > são usados para operadores de comparação no TeX e alguns desses caracteres são encontrados inigualáveis em comentários ou escapados.

    
por 01.10.2017 / 11:18
3

Eu não conheço nenhum programa que verifique apenas o pareamento correto de colchetes sem incomodar você com outros erros de sintaxe não relacionados, dependendo do idioma para o qual esses marcadores são direcionados.

Como, como você disse, é fácil escrever uma ferramenta desse tipo, aqui está um pequeno script que, esperamos, fará o trabalho:

#!/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

Se a sua implementação de sed não suportar o operador de alternância de \| (não padrão), você poderá substituir o comando s por 4:

s/\[\]//g
s/{}//g
s/()//g
s/<>//g

O comando tr acima é padrão, mas alguns (baseados no SysV) reclamarão de um [ sem escape contendo um intervalo. Com esses, você pode escapar do [ com \ ( tr -cd '{}()<>\[]' ), mas então ele não é especificado por POSIX e alguns não conseguiriam excluir o caractere de retrocesso. Para portabilidade, em sistemas baseados em ASCII, você pode usar tr -cd '{}()<>35' .

    
por 01.10.2017 / 01:35