如何通过regexp删除尾随注释?

Rod*_*uis 8 regex string matlab parsing

对于非MATLAB的读者:不确定他们属于哪个系列,但是这里将详细介绍MATLAB正则表达式.MATLAB的注释字符是%(百分比),其字符串分隔符是'(撇号).字符串内的字符串分隔符写为double-apostophe('this is how you write "it''s" in a string.').更复杂的是,矩阵转置运算符也是撇号(A'(Hermitian)或A.'(常规)).

现在,由于黑暗的原因(我不会详细说明:),我试图用MATLAB自己的语言解释MATLAB代码.

目前我正在尝试删除字符串单元格数组中的所有尾随注释,每个字符串都包含一行MATLAB代码.乍一看,这似乎很简单:

>> str = 'simpleCommand(); % simple trailing comment';
>> regexprep(str, '%.*$', '')
ans =
    simpleCommand(); 
Run Code Online (Sandbox Code Playgroud)

但是,当然,这样的事情可能会出现:

>> str = ' fprintf(''%d%*c%3.0f\n'', value, args{:}); % Let''s do this! ';
>> regexprep(str, '%.*$', '') 
ans = 
    fprintf('        %//   <-- WRONG!
Run Code Online (Sandbox Code Playgroud)

显然,我们需要从匹配中排除驻留在字符串内的所有注释字符,同时还要考虑直接在语句后面的单个撇号(或点 - 对照)是运算符,而不是字符串分隔符.

基于以下假设:注释字符的字符串打开/关闭字符数必须是偶数(我知道这是不完整的,因为矩阵转置运算符),我想出了以下动态正则表达式来处理这种情况:

>> str = {
       'myFun( {''test'' ''%''}); % let''s '                 
       'sprintf(str, ''%*8.0f%*s%c%3d\n''); % it''s '        
       'sprintf(str, ''%*8.0f%*s%c%3d\n''); % let''s '       
       'sprintf(str, ''%*8.0f%*s%c%3d\n'');  '
       'A = A.'';%tight trailing comment'
   };
>> 
>> C = regexprep(str, '(^.*)(?@mod(sum(\1==''''''''),2)==0;)(%.*$)', '$1')
Run Code Online (Sandbox Code Playgroud)

然而,

C = 
    'myFun( {'test' '%'}); '              %// sucess
    'sprintf(str, '%*8.0f%*s%c%3d\n'); '  %// sucess
    'sprintf(str, '%*8.0f%*s%c%3d\n'); '  %// sucess
    'sprintf(str, '%*8.0f%*s%c'           %// FAIL
    'A = A.';'                            %// success (although I'm not sure why)
Run Code Online (Sandbox Code Playgroud)

所以我差不多了,但还不完全:)

不幸的是,我已经花了很多时间来思考这个并且还需要继续其他事情,所以也许有更多时间的其他人足够友好地思考这些问题:

  1. 字符串中的注释字符是我需要注意的唯一例外吗?
  2. 这样做的正确和/或更有效的方法是什么?

Amr*_*mro 5

您对使用未记录的功能有何看法?如果您不反对,可以使用该mtree函数来解析代码并删除注释.没有涉及regexp,我们都知道我们不应该尝试使用正则表达式解析无上下文的语法.

该函数是用纯M代码编写的MATLAB代码的完整解析器.据我所知,它是一个实验性的实现,但它已经被Mathworks在一些地方使用(这与MATLAB CodyContests用来测量代码长度的功能相同),并且可以用于其他有用的东西.

如果输入是字符串的cellarray,我们做:

>> str = {..};
>> C = deblank(cellfun(@(s) tree2str(mtree(s)), str, 'UniformOutput',false))
C = 
    'myFun( { 'test', '%' } );'
    'sprintf( str, '%*8.0f%*s%c%3d\n' );'
    'sprintf( str, '%*8.0f%*s%c%3d\n' );'
    'sprintf( str, '%*8.0f%*s%c%3d\n' );'
    'A = A.';'
Run Code Online (Sandbox Code Playgroud)

如果您已经在磁盘上存储了M文件,则可以将注释简单地删除为:

s = tree2str(mtree('myfile.m', '-file'))
Run Code Online (Sandbox Code Playgroud)

如果您想要查看评论,请添加: mtree(.., '-comments')


Moh*_*nia 4

这通过检查一个字符之前允许使用哪些字符来匹配共轭转置大小写

  1. 数字 2'
  2. 信件A'
  3. A.'
  4. 左括号、大括号和方括号A(1)'A{1}'以及[1 2 3]'

我现在能想到的就只有这些案例了。

C = regexprep(str, '^(([^'']*''[^'']*''|[^'']*[\.a-zA-Z0-9\)\}\]]''[^'']*)*[^'']*)%.*$', '$1')
Run Code Online (Sandbox Code Playgroud)

在你的例子中我们会返回

>> C = regexprep(str, '^(([^'']*''[^'']*''|[^'']*[\.a-zA-Z0-9\)\}\]]''[^'']*)*[^'']*)%.*$', '$1')

C = 

    'myFun( {'test' '%'}); '
    'sprintf(str, '%*8.0f%*s%c%3d\n'); '
    'sprintf(str, '%*8.0f%*s%c%3d\n'); '
    'sprintf(str, '%*8.0f%*s%c%3d\n');  '
    'A = A.';'
Run Code Online (Sandbox Code Playgroud)