Por que expressões regulares criadas com o construtor regex usam sintaxe diferente das expressões regulares interativas?

26

Portanto, usando o construtor de expressões regulares (Mx re-builder), localizando linhas que terminam em \ takes "\\ $", enquanto na pesquisa e substituição por regex, leva apenas "\ $". Eu esperava que o construtor regex construísse expressões diretamente utilizáveis. Então, o que explica essa diferença?

user2699
fonte
6
Ele cria expressões diretamente utilizáveis ​​no código.
abo-abo
11
@ abo-abo Essa é a resposta que eu estava procurando, não sabia que havia uma diferença entre o que é utilizável no código e o que é utilizável na interface do usuário. Parece contra-intuitivo que o reconstrutor use a sintaxe dos códigos, e o manual não diz, mas isso explica a diferença.
user2699
2
Para tornar o construtor regex mais útil para compor pesquisas interativas, dê uma olhada na página wiki do ReBuilder emacs , especialmente na reb-query-replacedefinição de função.
dfeich

Respostas:

29

Na verdade, existem quatro re-builderopções de sintaxe diferentes , e você pode alternar entre elas comC-cTAB

Dois são para os compiladores regexp na forma sexp rxe sregex(mas como o primeiro é mais abrangente e quase totalmente compatível com a sintaxe, você pode realmente ignorar o sregex, a menos que trabalhe com o código antigo que o usou).

As outras duas opções de sintaxe são read(o padrão) e string(que é a sintaxe que você usa interativamente).

A readsintaxe é a sintaxe 'code' - ou seja, conforme reconhecida pelo lisp reader - na qual você insere o regexp conforme a sintaxe de leitura para strings :

C-hig (elisp) Syntax for Strings RET

A stringsintaxe (que eu sempre considerei um nome desnecessariamente confuso neste contexto) é a sintaxe de uma sequência de expressões regulares que já foi lida e, portanto, não possui nenhum caractere de escape necessário ao escrever a sequência. Ou seja, esta é a sintaxe da expressão regular real , a mesma que você usa quando o Emacs solicita interativamente.

Se você deseja usar a sintaxe de string por padrão, adicione o seguinte ao seu arquivo init ou use M-x customize-option RET reb-re-syntax RET

(setq reb-re-syntax 'string)

Observe que você pode alternar entre a sintaxe de leitura e de seqüência de caracteres ao editar a regexp, sem perda de dados. Você também pode alternar dos formulários sexp para a sintaxe de leitura / string (naturalmente; compilar sexps para strings é para isso que servem essas bibliotecas), mas não pode ir na outra direção e gerar um sexp a partir de uma string. o re-builder lembra qual era o sexp, para que você não perca essa forma ao alterar a sintaxe; mas também não é atualizado se você modificar o regexp em uma sintaxe diferente e depois voltar. Em suma, se você estiver criando o regexp como um sexp, certifique-se de editá- lo apenas ao usar essa sintaxe.


Uma pegadinha com o rxsuporte é que ela está realmente usando a rx-to-stringfunção, que não é exatamente idêntica a usar a rxmacro no código. rxaceita um número arbitrário de argumentos de formulário e os trata como uma sequência implícita , enquanto rx-to-stringaceita apenas um único formulário, e qualquer sequência de nível superior deve ser explicitada '(sequence ...)ou equivalente.

Em resumo, quando você insere um formulário '(...)no reconstrutor, ele é processado como (rx-to-string '(...))e não(rx ...)

Observe também que um formulário inválido pode re-builderinterromper a atualização dinâmica das correspondências no buffer associado, mesmo após a validação do formulário. A C-cC-uligação para reb-force-updateé útil para resolver essas situações.


Por padrão, a linha de modo mostra "RE Builder" ao usar readou stringsintaxe, e "RE Builder Lisp" ao usar rxou sregexsintaxe, mas parece muito mais útil identificar a sintaxe específica em uso (especialmente para diferenciar entre reade string).

Se você instalar o delightpacote do GNU ELPA, poderá usar o seguinte para adicionar um indicador de sintaxe à linha de modo.

(let ((name '("Regexp[" (:eval (symbol-name reb-re-syntax)) "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))

Isso altera o nome do modo para "Regexp [read]" na readsintaxe e da mesma forma para os outros.

Ou, para incluir uma dica para a pegada rxvs rx-to-stringdescrita acima, faça a linha de modo dizer "Regexp [rx-to-string]" ao usar a rxsintaxe:

(let ((name '("Regexp["
              (:eval (symbol-name (if (eq reb-re-syntax 'rx)
                                      'rx-to-string
                                    reb-re-syntax)))
              "]")))
  (delight `((reb-mode ,name :major)
             (reb-lisp-mode ,name :major))))
phils
fonte