用于将PCRE正则表达式转换为emacs正则表达式的Elisp机制

时间:2012-02-02 18:53:24

标签: regex emacs elisp pcre

我承认喜欢PCRE正则表达式比使用emacs要好得多,如果没有其他原因,当我输入'('我几乎总是想要一个分组运算符。当然,\ w和类似的东西比其他等价物更方便。

但是,当然希望改变emacs的内部结构会很疯狂。但我认为应该可以从PCRE表达式转换为emacs表达式,并进行所有需要的转换,以便我可以写:

(defun my-super-regexp-function ...
   (search-forward (pcre-convert "__\\w: \d+")))

(或类似)。

任何人都知道可以执行此操作的elisp库吗?


编辑:从以下答案中选择回复...

哇,我喜欢从4天假期回来,找到一系列有趣的答案!我喜欢这两种解决方案的工作。

最后,看起来exec-a-script和直接elisp版本的解决方案都可以工作,但从纯粹的速度和“正确性”方法来看,elisp版本肯定是人们更喜欢的版本(我自己包括)。

4 个答案:

答案 0 :(得分:23)

https://github.com/joddie/pcre2el是此答案的最新版本。

  

pcre2elrxt(RegeXp Translator或RegeXp Tools)是一个用于在Emacs中处理正则表达式的实用程序,它基于regexp语法的递归下降解析器。除了将(一部分)PCRE语法转换为其Emacs等效语言之外,它还可以执行以下操作:

     
      
  • 将Emacs语法转换为PCRE
  •   
  • 将语法转换为rx,一种基于S表达式的regexp语法
  •   
  • 通过以rx形式显示解析树并突出显示相应的代码块来解开复杂的正则表达式
  •   
  • 显示与正则表达式匹配的字符串(产品)的完整列表,前提是列表是有限的
  •   
  • 提供regexp语法的实时字体锁定(目前仅适用于Elisp缓冲区 - TODO列表中的其他模式)
  •   

原始答案的文字如下......


这是一个quick and ugly Emacs lisp solution(编辑:现在更永久地定位here)。它主要基于pcrepattern手册页中的描述,并按令牌工作,只转换以下结构:

  • 括号分组( .. )
  • 交替|
  • 数字重复{M,N}
  • 字符串引用\Q .. \E
  • 简单字符转义:\a\c\e\f\n\r\t,{ {1}}和\x +八进制数字
  • 字符类:\\d\D\h\H\s\S,{{ 1}}
  • \v\V保持原样(使用Emacs自己的单词和非单词字符的想法)

对于更复杂的PCRE断言它没有做任何事情,但它确实试图在字符类中转换转义。对于包含类似\w之类的字符类的情况,这可以通过转换为具有交替的非捕获组来完成。

它通过了我为它编写的测试,但肯定存在错误,并且逐个令牌扫描的方法可能很慢。换句话说,没有保修。但也许它会为某些目的做足够多的工作。欢迎有兴趣的人士改进; - )

\W

答案 1 :(得分:8)

我对perl脚本做了一些小修改,我发现on perlmonks(从命令行获取值)并将其保存为re_pl2el.pl(如下所示)。然后,以下是将PCRE转换为elisp正则表达式的一个不错的工作,至少对于我测试的非外来情况。

(defun pcre-to-elre (regex)
  (interactive "MPCRE expression: ")
  (shell-command-to-string (concat "re_pl2el.pl -i -n "
                                   (shell-quote-argument regex))))

(pcre-to-elre "__\\w: \\d+") ;-> "__[[:word:]]: [[:digit:]]+"

它没有像perl的害羞{N,M}?构造那样处理一些“角落”案例,当然也没有代码执行等等,但它可能满足您的需求或者是一个良好的起点。因为你喜欢PCRE我认为你知道足够的perl来修复你经常使用的任何情况。如果不让我知道,我们可以解决它们。

我会更乐意使用一个脚本将正则表达式解析为AST,然后以elisp格式将其吐出(从那时起它也可能以rx格式吐出),但我找不到任何这样做的事情,当我应该研究我的论文时,似乎需要做很多工作。 :-)我觉得很难相信没有人这样做过。

以下是我的“改进版”re_pl2el.pl。 -i表示不要对字符串进行双重转义,-n表示不打印最终换行符。

#! /usr/bin/perl
#
# File: re_pl2el.pl
# Modified from http://perlmonks.org/?node_id=796020
#
# Description:
#
use strict;
use warnings;

# version 0.4


# TODO
# * wrap converter to function
# * testsuite

#--- flags
my $flag_interactive; # true => no extra escaping of backslashes
if ( int(@ARGV) >= 1 and $ARGV[0] eq '-i' ) {
    $flag_interactive = 1;
    shift @ARGV;
}

if ( int(@ARGV) >= 1 and $ARGV[0] eq '-n' ) {
    shift @ARGV;
} else {
    $\="\n";
}

if ( int(@ARGV) < 1 ) {
    print "usage: $0 [-i] [-n] REGEX";
    exit;
}

my $RE='\w*(a|b|c)\d\(';
$RE='\d{2,3}';
$RE='"(.*?)"';
$RE="\0".'\"\t(.*?)"';
$RE=$ARGV[0];

# print "Perlcode:\t $RE";

#--- encode all \0 chars as escape sequence
$RE=~s#\0#\\0#g;

#--- substitute pairs of backslashes with \0
$RE=~s#\\\\#\0#g;

#--- hide escape sequences of \t,\n,... with
#    corresponding ascii code
my %ascii=(
       t =>"\t",
       n=> "\n"
      );
my $kascii=join "|",keys %ascii;

$RE=~s#\\($kascii)#$ascii{$1}#g;


#---  normalize needless escaping
# e.g.  from /\"/ to /"/, since it's no difference in perl
# but might confuse elisp

$RE=~s#\\"#"#g;

#--- toggle escaping of 'backslash constructs'
my $bsc='(){}|';
$RE=~s#[$bsc]#\\$&#g;  # escape them once
$RE=~s#\\\\##g;        # and erase double-escaping



#--- replace character classes
my %charclass=(
        w => 'word' ,   # TODO: emacs22 already knows \w ???
        d => 'digit',
        s => 'space'
       );

my $kc=join "|",keys %charclass;
$RE=~s#\\($kc)#[[:$charclass{$1}:]]#g;



#--- unhide pairs of backslashes
$RE=~s#\0#\\\\#g;

#--- escaping for elisp string
unless ($flag_interactive){
  $RE=~s#\\#\\\\#g; # ... backslashes
  $RE=~s#"#\\"#g;   # ... quotes
}

#--- unhide escape sequences of \t,\n,...
my %rascii= reverse %ascii;
my $vascii=join "|",keys %rascii;
$RE=~s#($vascii)#\\$rascii{$1}#g;

# print "Elispcode:\t $RE";
print "$RE";
#TODO whats the elisp syntax for \0 ???

答案 2 :(得分:1)

此前最接近的工作是对M-x重建器的扩展,请参阅

http://www.emacswiki.org/emacs/ReBuilder

或叶文斌关于PDE的工作。

http://cpansearch.perl.org/src/YEWENBIN/Emacs-PDE-0.2.16/lisp/doc/pde.html

答案 3 :(得分:0)

可能相关的是visual-regexp-steroids,它扩展了查询替换以使用实时预览,并允许您使用不同的正则表达式后端,包括PCRE。